天天看点

hadoop之HDFS源码分析---HDFS通信协议

一、HDFS中提供两种通信协议

1.Hadoop RPC接口:HDFS中基于Hadoop RPC框架实现的接口

2.流式接口:HDFS中基于TCP或者HTTP实现的接口

二、下面先讲Hadoop RPC接口

Hadoop RPC调用使得HDFS进程能够像本地调用一样调用另一个进程中的方法,目前Hadoop RPC调用基于Protobuf实现,具体底层细节后面再讲,本章主要介绍Hadoop RPC接口的定义。接口定义在org.apache.hadoop.hdfs.protocol和org.apache.hadoop.hdfs.server.protocol包中,包括以下几个接口:

  • ClientProtocol:客户端和名字节点间的接口;
  • ClientDatanodeProtocol:客户端与数据节点的接口(这个方法主要是用于客户端获取数据节点信息时调用,真正的数据读写交互在流式接口进行)
  • DatanodeProtocol:数据节点与名字节点通信接口
  • InterDatanodeProtocol:数据节点与数据节点间的通信接口
  • NamenodeProtocol:第二名字节点与名字节点间的接口

    其他接口:主要包括安全相关接口,HA相关接口

  1. ClientProtocol

    ClientProtocol定义了所有由客户端发起的,由Namenode响应的操作,这个接口有80多个方法,可以分为以下几类:

    • HDFS文件读相关的操作
    • HDFS文件写以及追加写的相关操作
    • 管理HDFS命名空间的相关操作
    • 系统问题与管理相关的操作
    • 快照相关的操作
    • 缓存相关的操作
    • 其他操作

(1)读数据相关的方法

ClientProtocol中与客户端读取文件相关的方法主要有两个:getBlockLocations()和reportBadBlocks()。

客户端调用getBlockLocations()方法获取HDFS文件指定范围内所有数据块的位置信息,每个数据块的位置信息指的是存储这个数据块副本的所有Datanode的信息,而且会按照与当前客户端的距离远近排序;

客户端来调用reportBadBlocks()方法向Namenode汇报错误的数据块信息。

(2)写/追加写数据相关的方法

在HDFS客户端操作中最重要的一部分就是写入一个新的HDFS文件,或者打开一个已有的HDFS文件执行追加写操作。ClientProtocol中定义了8种方法支持HDFS写操作:

  • create() 方法用于在HDFS的文件系统目录树种创建一个新的空文件。然后再调用addBlock()方法获取存储文件数据的数据块的位置信息,最后客户端根据位置信息建立数据流管道写入数据。
  • append()方法用于打开一个已有的文件,如果这个文件的最后一个数据块没有写满,,则返回这个数据块的位置信息,如果写满,则新建一个数据块返回信息。
  • addBlock()客户端调用addBlock()方法向指定文件添加一个新的数据块,并获取数据块副本的所有数据节点的位置信息。
  • complete()当客户端完成了整个文件的写入操作后,会调用complete()方法通知Namnode。

    以上是正常情况,如遇到错误时,会有以下方法:

  • abandonBlock()当客户端获取了一个新的申请的数据块,发现无法建立到存储这个数据块副本的某些数据节点单位连接时,会调用这个方法通知名字节点放弃这个数据块,之后客户端再次调用addBlock()方法获取新的数据块,并在参数中将无法链接的节点传给名字节点,避免再次分到这个节点上。
  • getAdditionalDatanode()和updatePipeline()如果客户端已经成功建立了数据管道,在客户端写某个数据块,存储这个数据块副本的某个数据节点出现错误时,客户端首先会调用getAdditionalDatanode()方法向Namenode申请一个新的Datanode来替代出现故障的Datanode。然后客户端会调用updateBlockForPipepline()方法向Namenode申请为这个数据块分配新的时间戳,这样故障节点上的没能写完整的数据块的时间戳就会过期,在后续的块汇报操作中会被删除,最后客户端就可以使用新的时间戳建立新的数据管道,来执行对数据块的写操作。数据流管道建立成功后,客户端还需要调用updatePipeline()方法更新Namenode中当前数据块的数据管道信息。
  • renewLease() 当写的过程中clientfazh发生异常时,对于任意一个Client打开的文件都需要Client定期调用该方法更新租约,如果Namenodechangshiji长时间没有收到Client的租约更新消息,就会认为Client发生故障,这是就会触发一次租约恢复操作,关闭文件并且同步所有数据节点上这个文件数据块的状态,确保HDFS系统中这个文件是正确且一致保存的。

    如果写的时候Namenode节点出错,就涉及HDFS的HA,后面再讲。

(3)命名空间管理的相关方法

ClientProtocol中有很多重要的一部分操作时对Namenode命名空间的修改,我们知道FileSystom类也定义了对文件系统命名空间修改操作的API,HDFS则满足FileSystom类抽象的所有方法。

(4)系统问题与管理操作

ClientProtocol中另一个重要的部分就是支持DFSAdmin工具的接口方法,DFSAdmin是供HDFS管理员管理HDFS集群的命令行工具。

(5)快照相关操作

用户可以为HDFS的任意路径创建快照,快照保存了一个时间点上HDFS某个路径中所有数据的拷贝,快照可以将失效的集群回滚到之前一个正常的时间点上。

(6)缓存相关操作

用户可以指定一些经常被使用或者高优先级任务对应的数据,让他们常驻内存而不被淘汰到磁盘上。

(7)其他操作

2.ClientDatanodeProtocol

ClientDatanodeProtocol定义了Client和Datanode之间的接口,可以分为两部分:一部分是支持HDFS文件读取操作,另一部分是支持DFSAdmin中与数据节点管理相关的命令。

(1)getReplicaVisibleLength()

客户端调用该方法从数据节点获取某个数据块副本真实的数据长度。当客户端读取一个文件时,需要获取这个文件对应的所有数据块的长度,用于建立数据块的输入流,然后读取数据。

(2)getBlockLocalPathInfo()

HDFS对于本地读取,也就是Client和Datanode在同一物理机上时,调用该方法优化了文件读取。

(3)refreshNamenoders()

在用户管理员命令行中有一个'hdfs dfsadmindatanodehost:port'命令,用于出发指定的Datanode重新加载配置文件,该命令底层就是调用这个接口。

(4)deleteBlockPool()

在用户管理员命令行中有一个'hdfs dfsadmindatanode-deleteBlockPooldatanode-host:port blockpoolId[force]'命令,用于从指定Datanode删除blockpoolId对应的块池,如果force参数被设置,则强制删除。

。。。

3.DatanodeProtocol

DatanodeProtocol是Datanode和Namenode间的接口,Datanode会使用这个接口与Namenode握手、注册、发送心跳、进行全量或增量的数据块汇报。Namenode会在Datanode的心跳响应中携带名字节点指令(唯一途径)。

DatanodeProtocol定义的方法分为三类:Datanode启动相关、心跳相关以及数据块读写相关。

(1)Datanode启动相关方法

一个完整的Datanode启动操作会与Namenode进行4次交互,首先调用versionRequest()与Namenode进行握手操作,然后调用registerDatanode()向Namenode注册当前的Datanode,接着调用blockReport()汇报Datanode上存储的所有数据块,最后调用cacheReport()汇报Datanode缓存的所有数据块。

(2)心跳相关方法

Datanode会定期(由dfs.heartbeat.interval配置项配置,默认3秒)向Namenode发送心跳,如果Namenode长时间没有接到Datanode发送的心跳,则Namenode会认为该Datanode失败。

(3)数据块读写相关方法

Datanode在进行数据块读写操作时与Namenode交互的方法包括repotBadBlocks(),blockReceivedAndDeleted()以及commitBlockSynchronization()方法。

Datanode会调用repotBadBlocks()方法向Namenode汇报损坏的数据块,Datanode会在三种情况下调用:DataBlockScanner线程定期扫描数据节点上储存的数据块,发现数据块的校验出现错误时;数据流管道写数据时,Datanode接受了一个新的数据块,进行数据块校验操作出现错误时;进行数据块复制操作,Datanode读取本地存储的数据块时,发现本地数据块副本的长度小于Namenode记录的长度时。

Datanode会定期(默认5分钟,不可更改)调用blockReceivedAndDeleted()方法向Namenode汇报Datanode新接受的数据块或者删除的数据块。

commitBlockSynchronization()方法用于在租约恢复操作时同步数据块的状态。

(4)其他方法

4.InterDatanodeProtocol

Datanode与Datanode之间的接口,主要用于租约恢复操作。

二、流式接口

流式接口是HDFS中基于TCP或HTTP实现的接口,在HDFS中,流式接口包括了基于TCP的DataTransferProtocol接口,以及HA架构中的Active Namenode和Standby Namenode之间的HTTP接口。

1.DataTransferProtocol

2.Active Namenode和Standby Namenode之间的HTTP接口

由于Standby Namenode成功地将读入的editlog文件与当前的命名空间合并,从而始终保持着一个最新版本的命名空间,所以Standby Namenode只需定期将自己的命名空间写入一个新的fsimage文件,并通过HTTP协议将这个fsimage文件传回Active Namenode即可。

继续阅读