阅读源码第一步是要编译源码;
源码版本:hadoop2.6+ ~ hadoop2.7 这个范围均可,改动不是特别大
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 , 启动磁盘资源检查线程等工作)
具体内容,下一篇介绍