准备工作
首先在Maven中导入Hadoop相关依赖,这里用的是hadoop 3.1.3版本:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.abc</groupId>
<artifactId>Hdfs</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-hdfs-client</artifactId>
<version>3.1.3</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-log4j12</artifactId>
<version>1.7.30</version>
</dependency>
</dependencies>
</project>
1. 概述
 如图,NameNode启动时,主要的几个步骤分别是:
-
startHttpServer 启动9870端口服务; -
loadNamesystem 从磁盘加载镜像文件fsimage和edits编辑日志; -
createRpcServer 创建RPC服务端 -
checkAvailableResources 检查磁盘空间是否充足 -
datanodeManager.activate 心跳超时判断 -
bmSafeMode.avtive 安全模式
2. 解析
main→createNameNode→new NameNode→initialize→
NameNode主要的几个步骤,都是在initialize 方法中完成,所以先找到initialize:
先找到NameNode类的main() 方法,以及createNameNode :  createNameNode拉到最下面,有new NameNode,进入NameNode :  进入NameNode,有initialize() 方法: 
(1)startHttpServer
进入initialize 方法:  调用start() 开启httpServer: 
(2)loadNamesystem
 进入initialize中的loadNamesystem 方法,再进入loadFromDisk  从磁盘加载镜像文件FSImage 和编辑日志Edits : 
(3)createRpcServer
进入initialize中的createRpcServer  开启RPC服务端 
(4)startCommonServices→NameNodeResourceChecker、checkAvailableResources
进入initialize中的startCommonServices   调用重载的startCommonServices :  在NameNodeResourceChecker 中检查镜像文件和编辑日志的路径是否能存储100mb内容,即1024x1024x100=104857600; 如果不够会警告;  在checkAvailableResources 中判断磁盘是否够用,不够则false;    isResourceAvailable()方法来自一个接口,  退到areResourceAvailable中,Ctrl+Alt+B 找到CheckableNameNodeResource() 接口的实现类:  判断磁盘空间是否够用,duReserved 就是defaultValue即100mb,不足则会false: 
(5)startCommonServices→blockManager.active()→heartbeatManager.active()
退回startCommonServices,  进入blockManager.active() :  进入heartbeatManager.activate :  进入heartbeatManager是一个heartbeatThread线程:  调用heartbeatThread线程的start()方法,则找run()方法!  进入heartbeatCheck(): 判断是否是10分钟30秒   判断时间: 25+ 100010*3s,超过即视为DataNode挂掉: 
(6)startCommonServices→blockManager.active()→bmSafeMode.active(blockTotal)
返回blockManager.active()  进入bmSafeMode.active(blockTotal) : 如果areThreasholdsMet()为true,则离开安全模式,否则进入安全模式;  ①setBlockTotal 设置块的阀值: threshold也是阀值,是0.999,即总的块假设为1000个,则只要有999个都启动即允许有一个不启动,则可以正常 blockthrehold = 总块数*0.999  ②areThreasholdsMet() 判断正常启动的块是否大于了阀值blockThrehold,如果块大于了blockThrehold阀值,则返回true; 
到此,NameNode启动过程中的六大步骤完毕。
|