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 , 启动磁盘资源检查线程等工作)
具体内容,下一篇介绍