hadoop源码解析-HDFS通讯协议(下- DataNodeProtocol、InterDatanodeProtocol、NamenodeProtocol和流式接口)

HDFS的通讯协议

HDFS通讯协议

HDFS RPC接口

3.DataNodeProtocol

上篇文章中讲述到的ClientProtocol 和 DataNodeProtocol 都是由客户端发起调用的接口,接下来介绍服务器间的接口。

DataNodeProtocol接口是DataNode 与NameNode 间的接口,DataNode 会通过此接口与NameNode握手、注册、心跳、数据块上报等等操作 。 当DataNode 向 NameNode 发送心跳时,NameNode可以将需要执行的指令以 心跳返回接口 传递给DataNode ,这样当DataNode 收到心跳返回后,就可以执行NameNode 下发的指令了。

DataNodeProtocol 可分为3中类型:启动相关、心跳相关、数据块读写相关

1、启动相关:
一个完整的 DataNode 启动 会与NameNode 交互4次,也就是会调用4次 DataNodeProtocol 的方法:

  1. 调用versionRequest() 方法与NameNode进行握手操作
    versionRequest() 方法被调用时,会与NameNode 进行握手,NameNode 会返回一个NamespaceInfo对象,其中封装了当前HDFS集群的信息,包括版本号,集群ID等等信息,当DataNode拿到这个信息后,会比较集群信息和自己的版本是否能协同工作,如果当前DataNode 上本身就存储了数据,那么还会检查其 块池ID,文件系统ID,集群ID 是否匹配

  2. 调用registerDataNode() 向NameNode 注册当前DataNode
    当握手成功后,会调用registerDataNode() 向NameNode 注册当前DataNode,这个方法参数封装了DataNodeId以及相关的一系列信息(集群id,namespaceId) 等等,NameNode 也会检测DataNode 在注册的时候发送过来的信息,如果兼容才允许注册,否则会抛错

  3. 调用blockReport() 向NameNode 汇报当前节点上所有的块数据
    DataNode 在注册成功后,会将自己所有的块信息上报,方法含有3个参数,包含一个DataNode 标识,块池ID 和数据块列表,NameNode接受到消息时,会将上报的块信息与DataNode建立其对应的关联关系,同时在响应结果中携带相关指令,通知节点进行重新注册、发送心跳、备份或者删除DataNode 本地磁盘上的数据块,块上报在启动就会执行一次,后续会按照参数,按照一定的时间间隔进行数据上报

  4. 调用cacheReport() 汇报DataNode 缓存的所有数据块
    缓存上报逻辑跟块上报的逻辑一致,只是上报的是DataNode 中的缓存信息

2、心跳相关
在一个分布式系统的节点之间大多采用心跳来维护节点的健康状态,DataNode 会定期(由dfs.heartbeat.interval配置,默认3s)想NameNode 发送心跳,如果NameNode长时间没有收到DataNode 发送的心跳,则会认为该DataNode失效。DataNodeProtocol .sendHeartbeat() 方法就是用于汇报心跳的,汇报心跳的参数中携带了DataNode 的身份信息,其节点上的存储状态、缓存状态、正在写文件的连接数、读写使用的线程数等等。

而NameNode 在接收到心跳后,会返回给DataNode 一个指令以及当前NameNode 的HA状态。特别注意的是,在开启HA 的HDFS 集群中,DataNode 是需要向Active NameNode 和 Standby NameNode 同时发送心跳的,但是仅有Active NameNode 可以向DataNode 下发指令

3、数据块读写相关方法
在启动时,blockReport() 方法就是数据块的读写方法之一,类似的还有 reportBadBlocks、blockReceivedAndDeleted() 以及 commitBlockSynchronized() 等方法

  • reportBadBlocks()
    本方法与blockReport很类似,DataNode 会调用这个方法向NameNode 会报损坏的数据块,在以下情况下会调用本方法:
    (1)DataBlockScanner 线程定时扫描 数据节点上数据块,发现数据块的校验出现错误时;
    (2)数据流管道写数据时,DataNode 接受了一个新的数据块,进行数据块的校验时出现错误
    (3)进行数据块复制时,发现本地数据块副本的长度小于NameNode记录的长度,会认为该数据块无效

  • blockReceivedAndDeleted()
    本方法由DataNode定期调用(5分钟,不可配置)向NameNode汇报自己新接收到的数据块或者删除的数据块,blockReport 是在DataNode启动时,全量汇报一次,然后DataNode 在生命周期内定期的增量汇报块的变动,以下情况下会涉及到增量块汇报:
    (1)DataNode接收到一个新的数据块,可来自客户端的写入或者是别的DataNode 上的复制数据
    (2)DataNode删除了一个数据块,可能是因为该数据块的副本数过多,NameNode下发了删除数据块副本的指令

  • commitBlockSynchronized()
    本方法用于租约恢复操作时,同步数据块的状态,在租约恢复操作时,DataNode完成所有的租约恢复协调操作后,调用本方法,同步DataNode和NameNode上的数据块的状态

4、其他方法
DataNodeProtocol中的最后一个方法是errorReport(),本方法用于向NameNode上报运行过程中的一些错误状态,比如磁盘不可用等等

5、DataNodeCommand
根据前文所知,在sendHeartbeat()、blockReport() 等方法被调用时,都会返回携带NameNode 向DataNode下发的指令,DataNodeCommand类就是描述NameNode 想DataNode 下发指令的父类,其包含很多子类。在RPC调用后,NameNode 通过返回DataNodeCommand,告知DataNode 应该执行哪些指令,比如数据块复制、数据块删除、数据块恢复等等操作。

由此可见DataNodeProtocol 核心是用于DataNode 与NameNode 进行信息交互的接口,实现了心跳、块上报、缓存上报、错误上报等一系列分布式系统中,各个组件之间的配合相关的功能,同时根据返回参数,实现了NameNode针对DataNode 的一些控制


4.InterDatanodeProtocol

上文介绍了DataNode与NameNode 之间的接口,本节介绍DataNode 与DataNode之间的接口
InterDatanodeProtocol 接口主要用于租约恢复操作:
(1)当客户端打开一个文件进行写操作时,首先会获取这个文件的租约,并且还需要定期更新租约。
(2)当NameNode 的租约监控程序发现某个HDFS文件的租约长时间没有更新,就会认为写这个文件的客户端发生了异常
(3)此时就需要触发租约恢复操作: 所谓的租约恢复,就是同步数据流管道中所有DataNode 上该文件数据块的状态,并强制关闭这个文件
(4)租约恢复的操作并不是有NameNode来完成的,而是NameNode会从数据管道中选出一个DataNode作为主节点来进行恢复
(5)被选出来的DataNode会协调整个租约恢复的过程
(6)被选出来的DataNode会将数据管道中所有的DataNode上同一数据块的状态(时间戳和数据块长度)同步一致
(7)完成租约恢复后,主NameNode会调用DataNodeProtocol.commitBlockSynchronized() 方法同步该数据块的时间戳和数据块长度到NameNode 上,让NameNode 和DataNode 保持一致
(8)DataNode 相互之间同步数据块的状态是利用 InterDatanodeProtocol接口完成的
(9)首先主DataNode 会调用 InterDatanodeProtocol.initReplicaRecovery() 方法获取数据流管道中所有DataNode 节点上 保存的指定数据块的状态
(10)主恢复节点会根据返回状态信息,确定当前数据块的新长度,并使用NameNode下发的recoverId作为数据块的新时间戳
(11)主节点确定好数据块的新状态后(长度+时间戳),会调用InterDatanodeProtocol.updateReplicaUnderRecovery() 将数据流管道中的所有的DataNode(存储当前数据块的所有DataNode)同步为新的长度+新的时间戳
(12)恢复完成后,主DataNode 会调用 DataNodeProtocol.commitBlockSynchronization() 方法将 当前数据块的新状态信息同步给 NameNode


5.NamenodeProtocol

本接口主要用于SecondaryNameNode 与 NameNode之间的通讯,用于协助NameNode完成fsimage 文件和 edits 文件的合并,在HA架构下,SecondaryNameNode 的功能被 Standby NameNode完全替代


6. 流式接口

HDFS 处理定义RPC调用接口外,还定义了流式接口,通过上文可知,上述的RPC接口核心在基础信息,元数据信息的通讯交流,对于数据文件如何上传、下载并未提及。因为在HDFS 中,定义了基于TPC 的 DataTransferProtocol 接口,用于具体的数据块的上传下载,以及HA架构中 Active NameNode 和 StandByNameNode之间的HTTP 接口

6.1 DataTransferProtocol

DataTransferProtocol 是用来描述写入或者读出 DataNode 上的数据 的 基于TCP 的流式接口,HDFS 客户端与数据节点、数据节点与数据节点之间 的数据块传输就是基于 DataTransferProtocol 接口实现的。HDFS 未采用Hadoop RPC 来实现HDFS 的读写功能,因为 Hadoop 的RPC框架的效率还不足以支撑超大文件的读写
(1)readBlock():从当前DataNode读取指定的数据块
(2)writeBlock():将指定的数据块写入到数据流管道中
(3)transferBlock():将指定的数据块复制到另外一个DataNode上
(4)replaceBlock():从源DataNode将数据块写入到本地DataNode,写入成功后通知原DataNode删除数据块,用于数据块平衡
(5)copyBlock():复制当前DataNode上的数据块,这个方法主要用于数据块平衡操作
(6)blockChecksum():获取指定数据块的校验和
(7)requestShortCiruitFds():获取一个短路读取数据块的文件描述符
(8)releaseShorttCiruitFds():释放一个短路读取数据块的文件描述
(9)requestShortCiruitShm():获取保存短路读取数据块的共享内存

DataTransferProtocol 接口调用并没有使用Hadoop RPC框架提供的功能,而是定义了用于发送请求的Sender 类,用于响应请求的Receiver类,Sender 和 Receiver都实现了 DataTransferProtocol 接口;当DFSClient 发起了一个 DataTransferProtocol .readBlock() 操作,DFSClient 首先会调用 Sender 将这个请求序列化,并传输给远端的 Receiver。远端的 Receiver接受到请求,会反序列化请求,然后调用代码执行读取操作

在这里插入图片描述

6.2 Active NameNode 与 Standby NameNode之间的HTTP 接口

NameNode 会定期将文件系统的 namespace(文件目录树、文件\目录的元数据)保存到 fsimage 的二进制文件中,防止NameNode掉电或者崩溃时,namespace 丢失从而导致文件系统的崩溃。如果NameNode 在每一次针对文件的修改都去同步写入到fsimage 文件中,将会导致NameNode非常消耗资源且运行缓慢。所以NameNode会将namespace 的修改操作保存到edits 文件中,该文件记录了针对hdfs namespace的修改指令,且是顺序写入的,效率非常高

但是由于HDFS 长时间运行,会导致edits 文件会越来越大,因此必须要进行 fsimage 和edits 文件的合并操作,在 Hadoop2.x 之前,HDFS 使用的是SecondaryNameNode 来合并 fsImage 的,但是其一样会丢失 edits_inprogress 的这一部分元数据

在Hadoop2.x 以后,引入了HA架构,Standby NameNode 不仅是Active NameNode 的一个热备,同时也是负责 fsimage 与edits 文件合并的工作,Standby NameNode 通过共享文件系统,源源不断的同步 Active NameNode 的修改操作,并定期将自己 namespace 生成一个新的fsimage 文件,当Standby 生成新的fsimage 时,会向Active 发送 HTTP请求, 请求中包含了新的fsimage 的文件事务ID以及 Standby 用于下载的端口和IP地址,Active 收到请求后,会向Standby 发送下载的HTTP 请求,下载新的fsimage 文件,并删除事务id 之前的 edits 文件

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值