1、NameNode启动流程的初始化操作

 

 阅读源码第一步是要编译源码;

源码版本:hadoop2.6+ ~ hadoop2.7 这个范围均可,改动不是特别大

编译源码教程连接:https://www.jianshu.com/p/a66ab0235fb9

https://www.cnblogs.com/hequn/articles/4839689.html

ps. 编译出错很常见不要慌 ,只要确保hadoop需要的依赖是正确的(比如protocol),就没问题!

1、查看源码NameNode类

在namenode中有一段main函数,说明 我们通过命令启动namenode的时候,肯定是通过这个main函数来执行的(脚本:hadoop-daemon.sh  、hdfs):

 1 public static void main(String argv[]) throws Exception {
 2     if (DFSUtil.parseHelpArgument(argv, NameNode.USAGE, System.out, true)) {
 3       System.out.println("####参数校验#####");
 4       System.exit(0);
 5       //hadooop namenode -format
 6       //hadoop -datemon.sh start namenode
 7       //hadoop-datemon.sh start nn
 8     }
 9 
10     try {
11       //启动打印日志
12       StringUtils.startupShutdownMessage(NameNode.class, argv, LOG);
13       //TODO 创建NameNode核心代码
14       NameNode namenode = createNameNode(argv, null);
15       if (namenode != null) {
16         //就是线程的join
17         //会使主线程进入等待池并等待t线程执行完毕后才会被唤醒
18         namenode.join();
19       }
20     } catch (Throwable e) {
21       LOG.error("Failed to start namenode.", e);
22       terminate(1, e);
23     }
24   }

 

 

2、查看核心代码:createNameNode

NameNode namenode = createNameNode(argv, null);

点击进入createNameNode(argv , null)函数

显然我们是启动namenode,所有都匹配不上,因此会走最后一段

 1 public static NameNode createNameNode(String argv[], Configuration conf)
 2       throws IOException {
 3     LOG.info("createNameNode " + Arrays.asList(argv));
 4     if (conf == null)
 5       conf = new HdfsConfiguration();
 6     StartupOption startOpt = parseArguments(argv);
 7     if (startOpt == null) {
 8       printUsage(System.err);
 9       return null;
10     }
11     //将启动参数加入到配置中
12     setStartupOption(conf, startOpt);
13     /**
14      * 我们在集群中操作 , 比如 :
15      * hdfs namenode -format
16      * hadoop fs -put XXX /
17      * 正常情况下,是先启动namenode
18      * hadoop-daemon.sh start namenode
19      * */
20     switch (startOpt) {
21       //格式化
22       case FORMAT: {//hadoop namenode -format
23         boolean aborted = format(conf, startOpt.getForceFormat(),
24                 startOpt.getInteractiveFormat());
25         terminate(aborted ? 1 : 0);
26         return null; // avoid javac warning
27       }
28       // 产生集群ID.
29       case GENCLUSTERID: {
30         System.err.println("Generating new cluster id:");
31         System.out.println(NNStorage.newClusterID());
32         terminate(0);
33         return null;
34       }
35       //定版本
36       case FINALIZE: {
37         System.err.println("Use of the argument '" + StartupOption.FINALIZE +
38                 "' is no longer supported. To finalize an upgrade, start the NN " +
39                 " and then run `hdfs dfsadmin -finalizeUpgrade'");
40         terminate(1);
41         return null; // avoid javac warning
42       }
43       //回滚
44       case ROLLBACK: {
45         boolean aborted = doRollback(conf, true);
46         terminate(aborted ? 1 : 0);
47         return null; // avoid warning
48       }
49       //同步active节点的快照(配置完HA需要运行这个命令同步active节点的快照(配置完HA需要运行这个命令
50       case BOOTSTRAPSTANDBY: {
51         String toolArgs[] = Arrays.copyOfRange(argv, 1, argv.length);
52         int rc = BootstrapStandby.run(toolArgs, conf);
53         terminate(rc);
54         return null; // avoid warning
55       }
56       //向备用节点共享一组edits日志
57       case INITIALIZESHAREDEDITS: {
58         boolean aborted = initializeSharedEdits(conf,
59                 startOpt.getForceFormat(),
60                 startOpt.getInteractiveFormat());
61         terminate(aborted ? 1 : 0);
62         return null; // avoid warning
63       }
64       //启动冷备或者温备名字节点
65       case BACKUP:
66       case CHECKPOINT: {
67         NamenodeRole role = startOpt.toNodeRole();
68         DefaultMetricsSystem.initialize(role.toString().replace(" ", ""));
69         return new BackupNode(conf, role);
70       }
71       //恢复损坏的元数据以及文件系统
72       case RECOVER: {
73         NameNode.doRecovery(startOpt, conf);
74         return null;
75       }
76       //检查配置的正确性
77       case METADATAVERSION: {
78         printMetadataVersion(conf);
79         terminate(0);
80         return null; // avoid javac warning
81       }
82       //以升级的方式启动
83       case UPGRADEONLY: {
84         DefaultMetricsSystem.initialize("NameNode");
85         new NameNode(conf);
86         terminate(0);
87         return null;
88       }
89       //正常启动NameNode
90       default: {
91         //初始化metric系统
92         DefaultMetricsSystem.initialize("NameNode");
93         //TODO
94         return new NameNode(conf);
95       }
96     }
97   }

NameNode这个类,里面有一些成员变量,还是很重要,很常见的;比如

 1 //NameNode核心成员变量用来管理元数据(实现对DataNode、Block的管理以及读写日志)
 2   protected FSNamesystem namesystem;
 3   //保存配置文件的信息
 4   protected final Configuration conf;
 5   //保存NameNode的角色信息
 6   protected final NamenodeRole role;
 7   //保存NameNode的状态(HA)
 8   private volatile HAState state;
 9   //是否开启了高可用(HA)
10   private final boolean haEnabled;
11   //高可用上下文
12   private final HAContext haContext;
13   //NameNode核心成员变量提供RPC服务(提供RPC服务是DataNode和NameNode通信和外部命令管理NameNode的窗口)
14   private NameNodeRpcServer rpcServer;

在这个Namenode的构造参数里面,主要是:

1、对namenode做参数的设置(fs.defaultFS、rpc地址等)

2、初始化

3、根据初始化处理的结果,namenode进入对应的状态(active、backup、standby)

 1 /**
 2    * 1、对namenode做参数的注册(fs.defaultFS、rpc地址等)
 3    * 2、初始化
 4    * 3、根据初始化处理的结果,namenode进入对应的状态(active、backup、standby)
 5    * */
 6   protected NameNode(Configuration conf, NamenodeRole role) 
 7       throws IOException { 
 8     this.conf = conf;
 9     this.role = role;//保存NameNode的角色信息
10     //设置clients访问nomenode或nameservice的访问地址  配置项fs.defaultFS:hadoop01:9000
11     setClientNamenodeAddress(conf);
12     String nsId = getNameServiceId(conf);
13     String namenodeId = HAUtil.getNameNodeId(conf, nsId);
14     //ha相关
15     this.haEnabled = HAUtil.isHAEnabled(conf, nsId);
16     //根据用户设置的启动参数,确定启动以后的初始状态,如果是正常启动,则全部直接进入Standby状态
17     state = createHAState(getStartupOption(conf));
18     this.allowStaleStandbyReads = HAUtil.shouldAllowStandbyReads(conf);
19     //TODO 在创建HA的时候,也启动了standByNameNode的服务
20     this.haContext = createHAContext();
21 
22 
23 
24     try {
25       //给联邦模式下准备的,主要是设置联邦模式下namenode的地址和RPC地址
26       initializeGenericKeys(conf, nsId, namenodeId);
27       //TODO
28       initialize(conf);
29       // HA相关
30       try {
31         haContext.writeLock();
32         state.prepareToEnterState(haContext);
33         state.enterState(haContext);
34       } finally {
35         haContext.writeUnlock();
36       }
37     } catch (IOException e) {
38       this.stop();
39       throw e;
40     } catch (HadoopIllegalArgumentException e) {
41       this.stop();
42       throw e;
43     }
44     this.started.set(true);
45   }

 

 

那么关键信息 就是initialize,所以我们接下来重点来看initialize

initialize代码块包含了:

1、metrics监控的信息设置
2、hadoop的kerberos的安全认证
3、启动namendoe的web服务
4、加载元数据
5、创建RPC
6、启动公共服务startCommonServices (比如:启动RPC , 启动磁盘资源检查线程等工作)

具体内容,下一篇介绍

 

posted @ 2020-03-31 23:34  niutao  阅读(2036)  评论(0编辑  收藏  举报