从bin/hadoop中可知,NameNode节点对应的类NameNode类,它的源代码文件是hdfs/org/apache/hadoop/hdfs/server/namenode/NameNode.java。
NameNode启动执行函数的次序:
[1]. 执行main函数。
[2].在main函数中执行createNameNode函数,得到NameNode的实例namenode。
[3].在createNameNode中,获取配置conf。Hadoop用Configuration类管理配置。
1.Configuration类
根据Hadoop的API可以,Hadoop的配置由Configuration类进行管理。配置由资源指定。资源由形如xml格式的名/值对设置和保存的。名又分两种,一种是字符串,另一种是Path类型的对象。Hadoop默认有两个资源,即字符串”core-default.xml”和”core-site.xml”。
通常来说,字符串资源就是文件名,Configuration类得到字符串资源后,会在Java的ClassPath中寻找字符串对应的文件,然后从文件里读取配置。如果资源是Path类型的对象,就直接从对象中读取配置,不需要检测ClassPath了。
Configuration类在实例化的时候,这一段代码先执行:
-
static{
ClassLoader cL =Thread.currentThread().getContextClassLoader();
if (cL == null) {
cL =Configuration.class.getClassLoader();
}
...
addDefaultResource("core-default.xml");
addDefaultResource("core-site.xml");
}
这一段代码载入两个默认资源。
然后再执行下面这段代码,获取classLoader:
-
{
classLoader =Thread.currentThread().getContextClassLoader();
if (classLoader == null){
classLoader =Configuration.class.getClassLoader();
}
}
然后执行构造函数Configuration()。
然后执行构造函数Configuration(true)。
至此,Configuration类实例化完成。
Configuration管理配置是一种“懒加载”的方式,添加资源之后,并不立即更新所有配置,而是做一个标记,其他函数读取配置的时候,先检查这个标记,如果标记指明需要更新配置,再从配置文件中更新全部配置,然后再读取所需要的值。
Configuration类负责读取配置的函数是loadResource函数,函数原型如下:
private voidloadResource(Properties properties, Object name, boolean quiet)
它的形参name可以是URL,可以是字符串,可以是Path等等诸多类型。比如说,如果name是字符串类型,也就是文件名,那么就由classLoader在ClassPath中找到这个文件,返回URL的绝对路径文件名,然后再从文件读取配置。
[4].在createNameNode函数中,调用parseArguments函数处理输出参数argv。在默认情况下,argv是空的,parseArguments函数的返回值是StartupOptionstartOpt枚举类型变量REGULAR,REGULAR的值是字符串”-regular”。
[5]. 在createNameNode函数中,调用setStartupOption函数设置配置参数,也就是将dfs.namenode.startup设置成字符串”-regular”。
[6].在createNameNode函数中,调用DefaultMetricsSystem.initialize函数初始化NameNode,语句如下:
DefaultMetricsSystem.initialize("NameNode");
2.DefaultMetricsSystem类
DefaultMetricSystem,默认度量系统,主要是为监控Hadoop集群提供接口。DefaultMericsSystem类实现了MetricsSystem接口。MetricsSystem接口继承MetricsSystemMXBean接口。
DefualtMetricsSystem以枚举类型实现了Singleton模式,确保只有一个NameNode的度量系统。
DefaultMericsSystem调用initialize函数初始化,最终是调用MetricsSystemImpl类的init函数进行初始化。
MetricsSystemImpl类的init函数执行两个函数,start函数和initSystemMBean函数。 在start函数,主要执行两个函数:configure函数和startTimer函数。configure函数为NameNode创建MetricConfig对象,然后初始化配置槽,资源,和系统。startTimer函数,启动一个Timer计时。
[7].在createNameNode函数中,创建一个NameNode类的namenode对象,然后返回。在NameNode类的构造函数,NameNode的构造函数主要执行initialize函数,initialize函数的主要任务是,进行安全认证,然后启动RPCServer,再启动HttpServer。
[8].在main函数中,namenode执行join函数。这个join函数,也就是执行RPCServer的join函数,执行wait函数,等待被结束。
[9].RPC的Server类里,有一个线程类Listener对象,一个线程类Responser对象,一个线程对象Handler数组,它们在NameNode的生命周期内始终运行。Listener对象监听Socket端口,把接收到的RPC命令记录到callQueue。线程对象Handler数组从callQueue取出RPC命令,执行RPC命令,然后把结果传给Responder对象。Responder对象把RPC结果返回给调用方。