HDFS的NameNode源码分析
1.大致流程
NameNode.main() // 入口函数
|——createNameNode(); // 通过new NameNode()进行实例化
|——initialize(); // 方法进行初始化操作
|——startHttpServer(); // 启动HttpServer
|——loadNamesystem(); // 加载元数据
|——createRpcServer(); // 创建并初始化rpc server实例
|——startCommonServices();
|——namesystem.startCommonServices(); // 启动一些磁盘检查、安全模式等一些后台服务及线程
|——new NameNodeResourceChecker(); // 实例化一个NameNodeResourceChecker并准备出所有需要检查的磁盘路径
|——checkAvailableResources(); // 开始磁盘空间检查
|——NameNode.getStartupProgress(); // 获取StartupProgress实例用来获取NameNode各任务的启动信息
|——setBlockTotal(); // 设置所有的block,用于后面判断是否进入安全模式
|——blockManager.activate(); // 启动BlockManager里面的一堆关于block副本处理的后台线程
|——rpcServer.start(); // 启动rpcServer
|——join()
2.详细流程
/**
* 1、 在这个方法中执行了一系列的成员变量初始化
* 2、 进行安全认证
* |-- 去配置文件中找,是否进行了安全认证,如果进行了安全认证,则校验
* 3、 启动namenode上的http服务
* |-- hadoop在原有的http服务基础上自己进一步封装了HttpServer
* |-- 然后在这儿里面启动了httpServer.start();
* |--setupServlets(httpServer, conf) 从此处不难看出,http也是一种RPC,因为它也可以实现不同进程方法的调用
* 当然,这里面有我们比较熟悉的一些页面功能,都是通过httpServer实现的,比如:在50070页面浏览目录信息,就是通过这个 hadoop01:50070/listPaths/*
* 4、 namenode启动时从本地文件系统加载镜像并重做编辑日志
loadNamesystem(conf);
* 5、 创建hadoop的RPC服务
* |-- rpcServer = createRpcServer(conf)
* NameNodeRpcServer里面有两个主要的RPC服务:
* 1):clientRpcServer , 主要管理的协议是hdfs的客户端与NameNode的交互
* 2):serviceRpcServer , 主要管理的协议是DataNode与NameNode的交互
* 因为 NameNodeRpcServer里面有两个主要的RPC服务 ,所以在这个构造方法中,hadoop也将clientRpcServer和serviceRpcServer构造出来,
* 并给对应的RPC上绑定了很多的协议
* 最后把serviceRpcServer和clientRpcServer的服务地址绑定给namenode
*6、 startCommonServices(conf);
* 启动一些公共服务,NameNode的RPC服务就是在这里启动
* 1):进行资源的检查,检查是否有足够的磁盘来存储元数据
* 比如:hadoop-daemon.sh start namenode 这个时候就会检查存储元数据的磁盘,是否满足100M
* 2):进行安全模式检查,检查是否可以退出安全模式
* |-- namesystem.startCommonServices(conf, haContext);
* NameNode核心成员变量用来管理元数据(实现对DataNode、Block的管理以及读写日志)
* |-- nnResourceChecker = new NameNodeResourceChecker(conf);
* 需要检查3个涉及到元数据的目录:
* Namenode2个目录:fsimage、editlog(默认情况下这两个是在同一个目录)
* 高可用模式下的journalNode里面也有存储元数据的目录
* |-- checkAvailableResources(),检查可用资源是否足够:如果不够,日志打印警告信息,然后进入安全模式
* (主要是检查存储元数据的磁盘空间是否大于100M,如果不大于就进入安全模式)
* |-- setBlockTotal(),设置所有的block,用于后面判断是否进入安全模式
* |-- getCompleteBlocksTotal 获取所有正常使用的block个数
* |-- total - numUCBlocks
* |-- blockManager.activate(conf),启动等待复制线程和启动管理心跳服务
* |-- rpcServer.start(),启动NameNodeRpcServer服务
* */