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

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 void main (String argv[]) throws Exception {
// 判断参数是否是打印帮助信息
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 方法。这时候应该调用 namenode join 方法等待服务关闭
if (namenode != null ) {
namenode.join() ;
}
} catch (Throwable e) {
LOG .fatal( "Failed to start namenode." , e) ;
terminate ( 1 , e) ;
}
}

namenode初始化代码
protected NameNode (Configuration conf , NamenodeRole role)
throws IOException {
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() ;
throw e ;
} catch (HadoopIllegalArgumentException e) {
this .stop() ;
throw e ;
}
this . started .set( true ) ;
}


真正的初始化操作
protected void initialize (Configuration conf) throws IOException {
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 ,需要为他启动一个 httpserver namenode web 界面,一路点进去可以看到默认端口是 50070
if (NamenodeRole. NAMENODE == role ) {
startHttpServer(conf) ;
}

this . spanReceiverHost = SpanReceiverHost. getInstance (conf) ;
// 从硬盘中实例化 namesystem,namesystem 中初始化了 BlockManager CacheManager
loadNamesystem(conf) ;
// 创建 rpc 服务,主要是创建了 serviceRpcServer clientRpcServer 分别监听 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 = new JvmPauseMonitor(conf) ;
pauseMonitor .start() ;
metrics .getJvmMetrics().setPauseMonitor( pauseMonitor ) ;
// 启动 rpc 等服务(以及 standby namenode 的相关服务)
startCommonServices(conf) ;
}


启动其他的一些通用服务
private void startCommonServices (Configuration conf) throws IOException {
// 启动 namesystem 的相关服务,包括检查硬盘容量等
// 另外,进入 SafeMode 状态,等待 datanode 报告 block 情况
namesystem .startCommonServices(conf , haContext ) ;
registerNNSMXBean() ;
// standby namenode 启动 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()) ;
}
}

你可能感兴趣的:(hdfs2.6.2源码学习)