1.2.2 流式接口

HDFS除了定义RPC调用接口外,还定义了流式接口,流式接口是HDFS中基于TCP或者HTTP实现的接口。在HDFS中,流式接口包括了基于TCP的DataTransferProtocol接口,以及HA架构中Active Namenode和Standby Namenode之间的HTTP接口。

1.DataTransferProtocol

DataTransferProtocol是用来描述写入或者读出Datanode上数据的基于TCP的流式接口,HDFS客户端与数据节点以及数据节点与数据节点之间的数据块传输就是基于DataTransferProtocol接口实现的。HDFS没有采用Hadoop RPC来实现HDFS文件的读写功能,是因为Hadoop RPC框架的效率目前还不足以支撑超大文件的读写,而使用基于TCP的流式接口有利于批量处理数据,同时提高了数据的吞吐量

图1-7给出了DataTransferProtocol的方法定义,其中最重要的方法就是readBlock()和writeBlock()。

■ readBlock():从当前Datanode读取指定的数据块。

■ writeBlock():将指定数据块写入数据流管道(pipeLine)中。

■ transferBlock():将指定数据块复制(transfer)到另一个Datanode上。数据块复制操作是指数据流管道中的数据节点出现故障,需要用新的数据节点替换异常的数据节点时,DFSClient会调用这个方法将数据流管道中异常数据节点上已经写入的数据块复制到新添加的数据节点上。

图1-7 DataTransferProtocol接口

■ replaceBlock():将从源Datanode复制来的数据块写入本地Datanode。写成功后通知NameNode,并且删除源Datanode上的数据块。这个方法主要用在数据块平衡操作(balancing)的场景下。

■ copyBlock():复制当前Datanode上的数据块。这个方法主要用在数据块平衡操作的场景下。

■ blockChecksum():获取指定数据块的校验值。

■ requestShortCircuitFds():获取一个短路(short circuit)读取数据块的文件描述符(请参考第5章的文件短路读操作小节)。

■ releaseShortCircuitFds():释放一个短路读取数据块的文件描述符。

■ requestShortCircuitShm():获取保存短路读取数据块的共享内存。

DataTransferProtocol接口调用并没有使用Hadoop RPC框架提供的功能,而是定义了用于发送DataTransferProtocol请求的Sender类,以及用于响应DataTransferProtocol请求的Receiver类,Sender类和Receiver类都实现了DataTransferProtocol接口。图1-8给出了DataTransferProtocol接口的一个调用示例。我们假设DFSClient发起了一个DataTransferProtocol.readBlock()操作,那么DFSClient会调用Sender将这个请求序列化,并传输给远端的Receiver。远端的Receiver接收到这个请求后,会反序列化请求,然后调用代码执行读取操作。

图1-8 DataTransferProtocol调用示例

DataTransferProtocol接口的具体实现我们会在第4章的流式接口小节中详细介绍,请读者参考该小节内容学习。

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

Namenode会定期将文件系统的命名空间(文件目录树、文件/目录元信息)保存到一个名叫fsimage的文件中,以防止Namenode掉电或者进程崩溃。但如果Namenode实时地将内存中的命名空间同步到fsimage文件中,将会非常地消耗资源且造成Namenode运行缓慢。所以Namenode会先将命名空间的修改操作保存在editlog文件中,然后定期合并fsimage和editlog文件。

合并fsimage和editlog文件是非常耗费资源的,所以在Hadoop 2.X版本之前,HDFS引入了一个第二名字节点专门负责合并fsimage和editlog文件。而在Hadoop 2.X版本中,由于Standby Namenode会不断地将读入的editlog文件与当前的命名空间合并,从而始终保持着一个最新版本的命名空间,所以Standby Namenode只需定期将自己的命名空间写入一个新的fsimage文件,并通过HTTP协议将这个fsimage文件传回Active Namenode即可。

Active Namenode和Standby Namenode之间的HTTP接口就是用来传输这个新的fsimage文件的。Standby Namenode成功地将自己的命名空间写入新的fsimage文件后,就会向Active Namenode的ImageServlet发送HTTP GET请求/getimage?putimage=1。这个请求的URL中包括了新的fsimage文件的事务ID,以及Standby Namenode用于下载的端口和IP地址。Active Namenode接收到这个请求后,会根据Standby Namenode提供的信息向Standby Namenode的ImageServlet发起HTTP GET请求以下载fsimage文件。

Active Namenode和Standby Namenode的内容请读者参考第3章的FSImage以及HA小节。