Hadoop源码学习笔记之NameNode启动场景流程四:rpc server初始化及启动
老规矩,还是分三步走,分别为源码调用分析、伪代码核心梳理、调用关系图解。
一、源码调用分析
根据上篇的梳理,直接从initialize()方法着手。源码如下,部分代码的功能以及说明,已经在注释阐述了。
- protected void initialize(Configuration conf) throws IOException {
- // 可以通过找到下面变量名的映射,在hdfs-default.xml中找到对应的配置
- if (conf.get(HADOOP_USER_GROUP_METRICS_PERCENTILES_INTERVALS) == null) {
- String intervals = conf.get(DFS_METRICS_PERCENTILES_INTERVALS_KEY);
- if (intervals != null) {
- conf.set(HADOOP_USER_GROUP_METRICS_PERCENTILES_INTERVALS,
- intervals);
- }
- }
- ......
- // 核心代码:启动HttpServer
- if (NamenodeRole.NAMENODE == role) {
- startHttpServer(conf);
- }
- this.spanReceiverHost = SpanReceiverHost.getInstance(conf);
- // 核心代码:FSNamesystem初始化
- loadNamesystem(conf);
- // 核心代码:创建一个rpc server实例
- rpcServer = createRpcServer(conf);
- ......
- // 核心代码:启动一些服务组件,包括rpc server等
- startCommonServices(conf);
- }
这段代码涉及到rpc server初始化及启动的核心,有两处:
第一处是rpcServer = createRpcServer(conf); 这个createRpcServer()的功能就是创建了一个rpc server的实例。如下:
- protected NameNodeRpcServer createRpcServer(Configuration conf)
- throws IOException {
- return new NameNodeRpcServer(conf, this);
- }
我们继续进去NameNodeRpcServer类的构造方法中看一看,到底里面做了哪些事情:
- public NameNodeRpcServer(Configuration conf, NameNode nn)
- throws IOException {
- this.nn = nn;
- this.namesystem = nn.getNamesystem();
- this.metrics = NameNode.getNameNodeMetrics();
- int handlerCount =
- conf.getInt(DFS_NAMENODE_HANDLER_COUNT_KEY,
- DFS_NAMENODE_HANDLER_COUNT_DEFAULT);
- RPC.setProtocolEngine(conf, ClientNamenodeProtocolPB.class,
- ProtobufRpcEngine.class);
// ----------1------------
// ---- 下面一堆都是实例化各种协议和服务的对象,所有的服务都是BlockingService接口的实现- // client和namenode之间进行通信需要调用的接口,包括:创建目录、管理block、设置权限等一些操作
- ClientNamenodeProtocolServerSideTranslatorPB
- clientProtocolServerTranslator = new ClientNamenodeProtocolServerSideTranslatorPB(this);
- BlockingService clientNNPbService = ClientNamenodeProtocol.
- newReflectiveBlockingService(clientProtocolServerTranslator);
- // datanode和namenode之间进行通信调用的接口,包括:datanode注册、heartbeatReport、blockReport等接口
- DatanodeProtocolServerSideTranslatorPB dnProtoPbTranslator =
- new DatanodeProtocolServerSideTranslatorPB(this);
- BlockingService dnProtoPbService = DatanodeProtocolService
- .newReflectiveBlockingService(dnProtoPbTranslator);
- // 不同的namenode之间进行通信需要调用的接口
- NamenodeProtocolServerSideTranslatorPB namenodeProtocolXlator =
- new NamenodeProtocolServerSideTranslatorPB(this);
- BlockingService NNPbService = NamenodeProtocolService
- .newReflectiveBlockingService(namenodeProtocolXlator);
- ......
// ---- 以上都是初始化rpc server关键的部分
// 确保供写数据的rpc服务引擎已经初始化,如果没有初始化,
// 则在此方法中调用registerProtocolEngine()从而将WritableRpcEngine引擎加入到内存中的引擎map- WritableRpcEngine.ensureInitialized();
- ......
if (serviceRpcAddr != null) {- ......
// -----------2----------
// 实例化一个监听datanode请求的rpc server- this.serviceRpcServer = new RPC.Builder(conf)
- .setProtocol(org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolPB.class)
- .setInstance(clientNNPbService)
- .setBindAddress(bindHost)
- .setPort(serviceRpcAddr.getPort()).setNumHandlers(serviceHandlerCount)
- .setVerbose(false)
- .setSecretManager(namesystem.getDelegationTokenSecretManager())
- .build();
- // 将前面实例化的各种协议service添加到这个监听datanode请求的rpc server
- // Add all the RPC protocols that the namenode implements
- DFSUtil.addPBProtocol(conf, HAServiceProtocolPB.class, haPbService,
- serviceRpcServer);
- DFSUtil.addPBProtocol(conf, NamenodeProtocolPB.class, NNPbService,
- serviceRpcServer);
- ......
- ......
- } else {
- ......
- }
- ......
- // -----------3------------
// 实例化一个监听客户端请求的rpc server- this.clientRpcServer = new RPC.Builder(conf)
- .setProtocol(
- org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolPB.class)
- .setInstance(clientNNPbService).setBindAddress(bindHost)
- .setPort(rpcAddr.getPort()).setNumHandlers(handlerCount)
- .setVerbose(false)
- .setSecretManager(namesystem.getDelegationTokenSecretManager()).build();
// 将前面实例化的各种协议service添加到这个监听客户端请求的RPC server- // Add all the RPC protocols that the namenode implements
- DFSUtil.addPBProtocol(conf, HAServiceProtocolPB.class, haPbService,
- clientRpcServer);
- DFSUtil.addPBProtocol(conf, NamenodeProtocolPB.class, NNPbService,
- clientRpcServer);
- ......
......- }
进入到NameNodeRpcServer类的构造方法中,可以看到除了上面几行的一些初始化赋值之外,下面的代码好长啊。其实并不复杂,
根据代码的逻辑划分,主要有三部分:
第一部分,实例化各种通信协议和服务对象,比如:负责创建目录、管理block、设置权限等操作的客户端同NameNode通信的
协议服务——ClientNameNodeProtocolServerSideTranslatorPB、负责datanode的启动时向NameNode注册、发送心跳报告、
block信息报告等操作的datanode同NameNode通信的协议服务——DatanodeProtocolServerSideTranslatorPB。篇幅有限,
后面还有不同NameNode之间通信协议服务、HA高可靠、用户权限管理等不在一一详细说明。
第二部分,实例化了一个监听datanode请求的rpc server,并且将第一部分实例化的各种ProtocolService同此rpc server进行绑定,
用于处理rpc server监听到的来自datanode的各种rpc请求。
第三部分,实例化了一个监听客户端请求的rpc server,并将第一部分实例化的各种ProtocolService同此rpc server进行绑定,用于
处理监听到的来自客户端的rpc请求。
至此,rpc server启动之前相关的准备工作已经完毕,接下来就要开始启动rpc server了。继续回到本篇刚开始的initialize()方法中的最后一处核心,
startCommonServices(); 内容如下:
- private void startCommonServices(Configuration conf) throws IOException {
// 核心代码:- namesystem.startCommonServices(conf, haContext);
- registerNNSMXBean();
- if (NamenodeRole.NAMENODE != role) {
- startHttpServer(conf);
- httpServer.setNameNodeAddress(getNameNodeAddress());
- httpServer.setFSImage(getFSImage());
- }
- // 启动rpcServer
- rpcServer.start();
- ......
- }
在此方法中,直接就启动了rpcServer。
但是在第一行的startCommonServices()方法也是核心之一,里面有很重要的一些服务,比如磁盘检查、安全模式判断等,后续篇幅会跟进。
二、伪代码调用流程梳理
NameNode.main() // 入口函数
|——createNameNode(); // 通过new NameNode()进行实例化
|——initialize(); // 方法进行初始化操作
|——startHttpServer(); // 启动HttpServer
|——loadNamesystem(); // 加载元数据
|——createRpcServer(); // 创建rpc server实例
|——new NameNodeRpcServer();
|——service1 // 各种通信协议service
|——service2 // 各种通信协议service
|——service.... // 各种通信协议service
|——serviceRpcServer = new RPC.builder(); // 实例化一个监听datanode请求的rpc server
|——serviceRpcServer.add(service1...); // 将各种service添加到serviceRpcServer
|——clientRpcServer = new RPC.builder(); // 实例化一个监听客户端请求的rpc server
|——clientRpcServer.add(service2...); // 将各种service添加到clientRpcServer
|——startCommonServices();
|——namesystem.startCommonServices(); // 启动一些磁盘检查、安全模式等一些后台服务及线程
|——rpcServer.start(); // 启动rpcServer
|——join()
三、rpc server初始化及启动流程图解
Hadoop源码学习笔记之NameNode启动场景流程四:rpc server初始化及启动的更多相关文章
- Hadoop源码学习笔记之NameNode启动场景流程一:源码环境搭建和项目模块及NameNode结构简单介绍
最近在跟着一个大佬学习Hadoop底层源码及架构等知识点,觉得有必要记录下来这个学习过程.想到了这个废弃已久的blog账号,决定重新开始更新. 主要分以下几步来进行源码学习: 一.搭建源码阅读环境二. ...
- Hadoop源码学习笔记之NameNode启动场景流程二:http server启动源码剖析
NameNodeHttpServer启动源码剖析,这一部分主要按以下步骤进行: 一.源码调用分析 二.伪代码调用流程梳理 三.http server服务流程图解 第一步,源码调用分析 前一篇文章已经锁 ...
- Hadoop源码学习笔记之NameNode启动场景流程五:磁盘空间检查及安全模式检查
本篇内容关注NameNode启动之前,active状态和standby状态的一些后台服务及准备工作,即源码里的CommonServices.主要包括磁盘空间检查. 可用资源检查.安全模式等.依然分为三 ...
- Hadoop源码学习笔记之NameNode启动场景流程三:FSNamesystem初始化源码剖析
上篇内容分析了http server的启动代码,这篇文章继续从initialize()方法中按执行顺序进行分析.内容还是分为三大块: 一.源码调用关系分析 二.伪代码执行流程 三.代码图解 一.源码调 ...
- Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构
Hadoop源码学习笔记(5) ——回顾DataNode和NameNode的类结构 之前我们简要的看过了DataNode的main函数以及整个类的大至,现在结合前面我们研究的线程和RPC,则可以进一步 ...
- Hadoop源码学习笔记(6)——从ls命令一路解剖
Hadoop源码学习笔记(6) ——从ls命令一路解剖 Hadoop几个模块的程序我们大致有了点了解,现在我们得细看一下这个程序是如何处理命令的. 我们就从原头开始,然后一步步追查. 我们先选中ls命 ...
- Hadoop源码学习笔记(2) ——进入main函数打印包信息
Hadoop源码学习笔记(2) ——进入main函数打印包信息 找到了main函数,也建立了快速启动的方法,然后我们就进去看一看. 进入NameNode和DataNode的主函数后,发现形式差不多: ...
- Hadoop源码学习笔记(1) ——第二季开始——找到Main函数及读一读Configure类
Hadoop源码学习笔记(1) ——找到Main函数及读一读Configure类 前面在第一季中,我们简单地研究了下Hadoop是什么,怎么用.在这开源的大牛作品的诱惑下,接下来我们要研究一下它是如何 ...
- Hadoop源码学习笔记(4) ——Socket到RPC调用
Hadoop源码学习笔记(4) ——Socket到RPC调用 Hadoop是一个分布式程序,分布在多台机器上运行,事必会涉及到网络编程.那这里如何让网络编程变得简单.透明的呢? 网络编程中,首先我们要 ...
随机推荐
- Android沉浸式状态栏
private void initWindows() { Window window = getWindow(); int color = getResources().getColor(androi ...
- linux下安装apache与php
http://www.92csz.com/study/linux/16.htm 1.apache 在如下页面下载apache的for Linux 的源码包 http://www.apache.org/ ...
- January 05 2017 Week 1st Thursday
The true nobility is in being superior to your previous self. 真正的高贵在于超越过去的自己. I will be satisfied if ...
- 51nod 1952 栈
题目链接戳这 如果只是从尾端插入,那么问题就是基础的:求取栈内最大值的问题,这用单调栈解决即可. 但是前端也能插入,一般的单调栈已经不能满足.那么想象,如果在前端插入一个小值,相当于在栈底多加一个值罢 ...
- Linux命令--压缩解压(简化版)
Linux tar.gz.tar.bz2.zip 等解压缩.压缩命令详解(简化版) Linux 常用的压缩与解压缩命令有:tar.gzip.gunzip.bzip2.bunzip2.compress ...
- Thinkphp 漏洞小试
首先确定这个网站使用thinkphp的框架 国内很多php开源项目的代码都是使用thinkphp框架编写的,但是thinkphp框架有很多版本,如何才能知道我们使用的框架是哪个版本的呢? 在URL后面 ...
- zk集群的快速搭建
1.上传一个zk.tar2.解压3.创建目录data4.修改zoo_sample.cfg ---> zoo.cfg5.修改文件的dataDir改为/data目录,echo 1 >/data ...
- $_cookie的使用
设置并发送 cookie: <?php $value = "my cookie value"; // 发送一个简单的 cookie setcookie("TestC ...
- 容器适配器(一):queue
除了标准的顺序容器外,STL还提供了3种容器适配器,queue,priority_queue和stack 适配器是对顺序容器的包装,它的作用是简化接口. queue接口十分的简单,只有8个方法.再加上 ...
- gem install redis安装时报错:redis requires Ruby version >= 2.2.2
Centos默认支持ruby到2.0.0,可gem 安装redis需要最低是2.2.2 解决办法是 先安装rvm,再把ruby版本提升至2.3.3 1.安装curl sudo yum install ...