hdfs2.6.2源码学习:Day1-NameNode启动流程分析

来源:互联网 发布:java string类排序 编辑:程序博客网 时间:2024/05/21 09:25
NameNode启动流程分析

一、shell调用梳理
启动hdfs的shell脚本是
${HADOOP_HDFS_HOME}/sbin/start-dfs.sh

其中在启动namenode、datanode、secondarynamenode、journalnode、zkfc等服务时都是调用了
${HADOOP_PREFIX}/sbin/hadoop-daemons.sh

其中会首先调用hadoop-config.sh,在这里加载了各种配置
然后调用

最终调用了/bin/hdfs

在hdfs脚本中,直接使用java命令调用了
org.apache.hadoop.hdfs.server.namenode.NameNode
org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode
org.apache.hadoop.hdfs.server.datanode.DataNode
等类

二、NameNode类分析

首先大致浏览了一下这个类,其中看到感兴趣的类就点进去大致看一眼,总体上看这个类的内容写的很明白

然后开始从入口看代码
public static voidmain(String argv[])throwsException {
//判断参数是否是打印帮助信息
if(DFSUtil.parseHelpArgument(argv,NameNode.USAGE,System.out, true)) {
System.exit(0);
}

try{
//打印startup信息,并且增加shutdown的钩子函数(该函数打印shutdown信息)
StringUtils.startupShutdownMessage(NameNode.class,argv,LOG);
//所有namenode相关启动命令调用统一的方法
NameNode namenode = createNameNode(argv, null);
//如果namenode不为null,则表明是调用的启动namenode方法。这时候应该调用namenodejoin方法等待服务关闭
if(namenode !=null) {
namenode.join();
}
}catch(Throwable e) {
LOG.fatal("Failed to start namenode.",e);
terminate(1,e);
}
}

namenode初始化代码
protectedNameNode(Configuration conf,NamenodeRole role)
throwsIOException {
this.conf= conf;
this.role= role;
setClientNamenodeAddress(conf);
String nsId = getNameServiceId(conf);
String namenodeId = HAUtil.getNameNodeId(conf,nsId);
this.haEnabled= HAUtil.isHAEnabled(conf,nsId);
state= createHAState(getStartupOption(conf));
this.allowStaleStandbyReads= HAUtil.shouldAllowStandbyReads(conf);
this.haContext= createHAContext();
try{
initializeGenericKeys(conf,nsId,namenodeId);
//这里真正初始化namenode服务
initialize(conf);
try{
haContext.writeLock();
state.prepareToEnterState(haContext);
state.enterState(haContext);
}finally{
haContext.writeUnlock();
}
}catch(IOException e) {
this.stop();
throwe;
}catch(HadoopIllegalArgumentException e) {
this.stop();
throwe;
}
this.started.set(true);
}


真正的初始化操作
protected voidinitialize(Configuration conf)throwsIOException {
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);
}
}
//设置ugi
UserGroupInformation.setConfiguration(conf);
loginAsNameNodeUser(conf);
//统计namenode各种信息
NameNode.initMetrics(conf, this.getRole());
StartupProgressMetrics.register(startupProgress);
//如果是正常服务的namenode,需要为他启动一个httpservernamenodeweb界面,一路点进去可以看到默认端口是50070
if(NamenodeRole.NAMENODE==role) {
startHttpServer(conf);
}

this.spanReceiverHost= SpanReceiverHost.getInstance(conf);
//从硬盘中实例化namesystem,namesystem中初始化了BlockManagerCacheManager
loadNamesystem(conf);
//创建rpc服务,主要是创建了serviceRpcServerclientRpcServer分别监听datanode和客户端的请求
rpcServer= createRpcServer(conf);
if(clientNamenodeAddress==null) {
// This is expected for MiniDFSCluster. Set it now using
// the RPC server's bind address.
clientNamenodeAddress=
NetUtils.getHostPortString(rpcServer.getRpcAddress());
LOG.info("Clients are to use " +clientNamenodeAddress+" to access"
+" this namenode/service.");
}
if(NamenodeRole.NAMENODE==role) {
httpServer.setNameNodeAddress(getNameNodeAddress());
httpServer.setFSImage(getFSImage());
}
pauseMonitor=newJvmPauseMonitor(conf);
pauseMonitor.start();
metrics.getJvmMetrics().setPauseMonitor(pauseMonitor);
//启动rpc等服务(以及standbynamenode的相关服务)
startCommonServices(conf);
}


启动其他的一些通用服务
private voidstartCommonServices(Configuration conf)throwsIOException {
//启动namesystem的相关服务,包括检查硬盘容量等
//另外,进入SafeMode状态,等待datanode报告block情况
namesystem.startCommonServices(conf,haContext);
registerNNSMXBean();
//standbynamenode启动http服务
if(NamenodeRole.NAMENODE!=role) {
startHttpServer(conf);
httpServer.setNameNodeAddress(getNameNodeAddress());
httpServer.setFSImage(getFSImage());
}
//启动rpc服务
rpcServer.start();
//加载rpc服务插件(自定义rpc调用方法)
plugins= conf.getInstances(DFS_NAMENODE_PLUGINS_KEY,
ServicePlugin.class);
for(ServicePlugin p:plugins) {
try{
p.start(this);
}catch(Throwable t) {
LOG.warn("ServicePlugin " + p +" could not be started",t);
}
}
LOG.info(getRole() + " RPC up at: "+rpcServer.getRpcAddress());
if(rpcServer.getServiceRpcAddress() != null) {
LOG.info(getRole() + " service RPC up at: "
+rpcServer.getServiceRpcAddress());
}
}