java hdfs 2.0_Hadoop源码学习笔记(2)--Hdfs的启动流程分析

Hdfs 的基础架构

c9711c1054c5

Hdfs基础架构

如上图所示。 默认情况下,Hdfs 由一个 Namenode 和多个 DataNode 组成。

hdfs作为一个分布式文件存储系统,他的文件路径和文件内容是相互隔离的。 文件路径信息保存在 NameNode 中,文件内容则分布式的保存在 DataNode中。

也就是说对于一个大文件,它可能被根据其文件大小切割成多个小文件进行存储,同时这些小文件可能被分布式的存储在不同的DataNode中。

当Client希望获取这个文件时,则需要先根据文件路径从 NameNode 中获取他对应的区块在不同的 DataNode 中的信息,然后才能够从 DataNode 中取出数据,还原成一个大文件。

具体的代码逻辑会在之后的读写操作中介绍,这里我们先看看 hdfs 集群的启动流程。

Hdfs 集群启动流程

默认情况下,我们通过 ${HADOOP_HOME}/sbin/start-dfs.sh 启动整个 Hdfs 集群。

hdfs namenode "${HADOOP_HDFS_HOME}/bin/hdfs" --workers --config "${HADOOP_CONF_DIR}" --hostnames "${NAMENODES}" --daemon start namenode ${nameStartOpt}

hdfs datanode "${HADOOP_HDFS_HOME}/bin/hdfs" --workers --config "${HADOOP_CONF_DIR}" --daemon start datanode ${dataStartOpt}

hdfs secondarynamenode "${HADOOP_HDFS_HOME}/bin/hdfs" --workers --config "${HADOOP_CONF_DIR}" --hostnames "${SECONDARY_NAMENODES}" --daemon start secondarynamenode

hdfs journalnode "${HADOOP_HDFS_HOME}/bin/hdfs" --workers --config "${HADOOP_CONF_DIR}" --hostnames "${JOURNAL_NODES}" --daemon start journalnode

hdfs zkfc "${HADOOP_HDFS_HOME}/bin/hdfs" --workers --config "${HADOOP_CONF_DIR}" --hostnames "${NAMENODES}" --daemon start zkfc

在 start-dfs.sh 文件中,我们看到shell文件通过执行hdfs命令先后启动 NameNode 、 DataNode 、 SecondaryNameNode 、 JournalNode。

hdfs也是一个shell文件,通过文本应用打开后,我们看到在该文件的执行逻辑如下:

c9711c1054c5

hdfs执行逻辑

节点类型和Java类的一一对应

在hdfs文件中可以看到,传入的第一个参数对应着需要启动节点的类型,使用 hdfscmd_case 根据节点类型可以找到对应需要执行的Java类,节点对应表如下。

节点类型

Java类

namenode

org.apache.hadoop.hdfs.server.namenode.NameNode

datanode

org.apache.hadoop.hdfs.server.datanode.DataNode

secondarynamenode

org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode

journalnode

org.apache.hadoop.hdfs.qjournal.server.JournalNode

Tips:类似datanode根据是否是secure mode会有多个Java类对应,但这里只列出最常用的类

为远程机器启动hdfs

通过解析节点类型,hdfs找到了对应的Java类。接下来就应该是启动并执行这个Java类。

但是如果在启动命令中包含了 --worker 参数,就代表着需要链接到其他节点机器上执行命令。在处理传参的时候,发现--worker后,会将 ${HADOOP_WORKER_MODE} 设置为 true, 从而执行 hadoop_common_worker_mode_execute(对应的方法逻辑在 hadoop-functions.sh 文件中)。在 hadoop_common_worker_mode_execute 中,通过读取配置文件信息,获取到真实运行设备的hostname,通过ssh执行一个不带--worker选项的hdfs命令,使得hostname对应的节点机器能够启动hdfs节点。

注意:如果需要通过这种方法启动远程机器,需要将启动机器的.ssh公钥加入被启动机器的信任列表中: cat target/id_rsa.pub >> ~/.ssh/authorized_keys,否则无法直接链接上对应设备

本地启动hdfs

我们通过ssh让远程设备启动hdfs节点时,会传递过去一个不带--worker的可执行命令。

因此通过hdfs启动节点时,运行逻辑和之前保持一致,只是${HADOOP_WORKER_MODE}不为true。此时通过判断是否需要在后台执行命令,我们分别通过 hadoop_daemon_handler 或者 hadoop_java_exec 在前台或后台启动对应的Java任务。

这里需要留意的是,在通过 hdfscmd_case 解析节点指令时,或默认将 ${HADOOP_DAEMON_MODE} 设置为 true,使得各个节点默认在后台运行。

NameNode 启动逻辑

NameNode在整个hdfs中扮演着一个很重要的角色,他负责整个文件系统的路径和数据的管理工作,比较类似 Unix 系统中的 inode table。

Client 通过 NameNode 获取到指定路径的分布式文件的 metadata,找到存放在 DataNode 的数据位置,就像从 inode talbe中获取 inode 编号,然后才能去访问具体的分布式文件。

从上一小节的表格中,我们看到 NameNode 对应的启动类是 org.apache.hadoop.hdfs.server.namenode.NameNode,接下来我们通过走读NameNode::main 具体查看节点的启动流程。

由于 NameNode 的启动参数很多,类似 FORMAT,CLUSTERID,IMPORT等等启动参数并不会被用来启动 NameNode。为了简单起见,这里只针对默认启动逻辑 REGULAR进行分析,启动流程如下:

c9711c1054c5

NameNode

如图所示,对于REGULAR模式而言,NameNode节点主要启动了下面三个组件:

c9711c1054c5

NameNode

NameNodeHttpServer

startHttpServer 会启动一个 NameNodeHttpServer。

NameNodeHttpServer 是一个基于 jetty 服务器的简单封装,提供给使用人员一个简单的节点状态查询页面,默认的绑定端口是 :9870,静态页面代码路径是 webapps/namenode,这一部分由于不涉及到核心逻辑,不做介绍。

FSNamesystem

loadNamesystem 会构建一个 FSNamesystem 对象,FSNamesystem 是 NameNode 中最核心的一个模块,负责处理维护整个分布式文件系统。详细的处理逻辑会在后续的章节做仔细介绍。

RPC.Server

createRPCServer 会启动一个 RPC.Server 线程。

RPC.Server 负责处理 hdfs 集群中的内部通信,在 RPC.Server 中绑定了一个 socket 端口,利用protobuf的序列化框架进行数据传输,关于 RPC.Server 的交互逻辑会在下一章中做详细介绍,这里可以简单理解为一个使用socket通信的rpc访问框架。

if (serviceRpcAddr != null) {

serviceRpcServer = new RPC.Builder(conf).build();

}

if (lifelineRpcAddr != null) {

lifelineRpcServer = new RPC.Builder(conf).build();

}

clientRpcServer = new RPC.Builder(conf).build()

在NameNodeRpcServer的构造方法中可能会构造 serviceRpcServer , lifelineRpcServer 和 clientRpcServer 三种 RPC.Server。

DataNode 启动逻辑

DataNode 在整个hdfs框架中负责具体的文件存储。

我们知道DataNode的启动类是org.apache.hadoop.hdfs.server.datanode.DataNode

c9711c1054c5

DataNode启动逻辑

他的启动逻辑如上图所示。和NameNode类似,在DataNode中同样启动了一个基于 jetty Server的 HTTP 服务器,负责向使用人员展示节点状态;同样还有一个基于 RPC.Server 的 socket 链接负责 hdfs集群 的内部通信。

c9711c1054c5

DataNode

DataXceiverServer

initDataXceiver 会启动一个 DataXceiverServer 类。

DataXceiverServer 负责接收通过TCP协议传输过来的文件数据,会在下一章介绍 hdfs 的文件传输的时候做介绍,这里先略过

DatanodeHttpServer

DatanodeHttpServer 和 NameNodeHttpServer 一样,也是一个基于 jetty 服务器的封装,负责向使用人员提供当前Datanode的节点状态信息,默认的启动端口是 :9864,静态页面代码路径 webapps/datanode,同样这一部分不设计核心逻辑,不做介绍

RPC.Server

DataNode中也存在一个RPC.Server对象,负责维持节点间通信,在下一篇文章中会做详细介绍。

BlockPoolManager

由于在hdfs中文件路径和文件内容是相互隔离的,在DataNode负责存放分布式的文件内容,但是对于DataNode自身并不知道自己的文件名,只有一个唯一的 blockId 用以定位文件信息。

在 BlockPoolManager 中,DataNode会定期上报当前节点的 blockId 列表,以便告知NameNode节点中拥有的文件内容。具体的逻辑会在 hdfs的文件传输的时候做介绍。

总结

在本文中,没有过多的对源码进行分析,只简单的介绍了 NameNode 和 DataNode 两个节点的启动逻辑。

原因很简单,每个子组件的内容都需要结合 NameNode 和 DataNode 甚至还需要 Client 三者结合来讲解。而且每个子组件的逻辑也会比较复杂,已经无法放在一个小节里进行讲述。

所以,本文中只有 start-dfs.sh 的启动逻辑和 NameNode 与 DataNode 的关键组件构成。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值