在前面几篇文章中已经分析完了IPC的调用的大致过程,接下来分析NameNode节点的工作过程
NameNode节点在HDFS文件系统中只有一个实例,它提供了与多个DataNode实例一起组成了HDFS系统。NameNode节点主要功能是维护着HDFS文件中两个重要的关系:
- HDFS文件系统的文件目录树,文件的数据块索引(即每个文件对应的数据块列表),
- 数据块和DataNode节点的对应关系(即一个数据块的多个副本分别保存在哪些DataNode节点上)。
其中HDFS目录树、元信息和数据块索引等信息会持久化到磁盘上,保存在命名空间镜像和编辑日志中。数据块和数据节点的对应关系则在NameNode节点和DataNode节点启动后,由DataNode节点上报给NameNode节点。NameNode节点通过接收数据节点的注册、心跳和数据块提交等信息来管理DataNode节点。NameNode节点会通过发送数据块复制、删除、恢复等NameNode节点指令来操作数据块,此外,NameNode节点还为客户端对文件系统目录树的操作和对文件数据读写以及对HDFS系统进行管理提供了支持。
NameNode的启动
在org.apache.hadoop.hdfs.server.namenode.NameNode.java文件中有个main函数,也就是启动NameNode节点的入口函数。NameNode类的main函数中通过方法createNameNode()创建了一个NameNode对象,然后就调用NameNode.join()函数等待NameNode停止。main()函数代码如下:
public static void main(String argv[]) throws Exception {
try {
StringUtils.startupShutdownMessage(NameNode.class, argv, LOG);
NameNode namenode = createNameNode(argv, null);
if (namenode != null)
namenode.join();
} catch (Throwable e) {
LOG.error(StringUtils.stringifyException(e));
System.exit(-1);
}
}
NameNode.join()函数就是调用NameNode.server成员变量的join方法,而NameNode.server成员变量是一个Hadoop IPC中讨论的RPC.Server对象,最终就调用了RPC.Server.join()方法。RPC.Server.join()方法也很简单,就是判断Server.runnning变量是否为true,如果running为true,说明这个IPC服务还在运行,就进入等待(wait()函数)。通过上面的分析可以知道,NameNode对象创建成功之后就可以为其他对象提供服务了,直到调用了NameNode的stop()方法,这部分代码比较简单,就不贴出来了。还有一点要注意的是NameNode的成员变量中有两个RPC.Server对象,一个是server,另一个是serviceRpcServer,其中server用于处理客户端的调用,serviceRpcServer用于处理HDFS内部的通信服务,如Datanode节点的调用。
NameNode类的main()方法中,最重要的就是NameNode namenode = createNameNode(argv, null);这行代码,通过这行代码创建了一个NameNode对象。下面以createNameNode()方法为入口来分析NameNode节点的启动过程。createNameNode()函数的代码如下:
public static NameNode createNameNode(String argv[],
Configuration conf) throws IOException {
if (conf == null)
conf = new Configuration();
StartupOption startOpt = parseArguments(argv);
if (startOpt == null) {
printUsage();
System.exit(-