客户端从HDFS中读取文件流程

(1)首先,客户端通过调用File System对象中的open()函数打开需要读取的文件。对于HDFS来说,File System是分布式文件系统的一个实例,对应图中的第一步。

(2)然后DistributedFileSystem通过远程过程调用(Remote Procedure Call,RPC)调用NameNode,以确定文件起始块的位置。对于每一个块,NameNode返回存有该块副本的DataNode的地址。这些返回的DataNode会按照Hadoop定义的集群网络拓扑结构计算自己与客户端的距离并进行排序,就近读取数据。若客户端本身就是一个DataNode节点,并保存有相应数据块的一个副本,则该节点就会直接读取本地数据块。

(3)HDFS会向客户端返回一个支持文件定位的输入流对象FSDataInputStream。FSDataInputStream类封装的DFSInputStream对象管理着NameNode和DataNode之间的I/O。当获取到数据块的位置后,客户端就会调用输入流的read()函数读取数据。存储着文件起始块DataNode的地址的DFSInput Stream对象随即连接距离最近的DataNode。

(4)连接完成后,DFSInputStream对象反复调用read()函数,将数据从DataNode传输到客户端,直到这个块全部读取完毕。

(5)当最后一个数据块读取完毕时,DFSInput Stream会关闭与该DataNode的连接,然后寻找下一个数据块距离客户端最近的DataNode。客户端从流中读取数据时,块是按照打开DFSInput Stream与DataNode新建连接的顺序读取的。它会根据需要询问NameNode来检索下一批数据块的DataNode的位置。

(6)一旦客户端完成读取,就会对FSDataInputStream调用close()。

在读取数据的时候,如果DFSInputStream与DataNode通信错误,会尝试读取该块最近邻的其他DataNode节点上的数据块副本,同时也会记住发生故障的DataNode,以保证以后不会去读取该节点上后续块。收到数据块以后,DFSInputStream也会通过校验和确认从DataNode发来的数据的完整性。如果块损坏,则DFSInputStream试图从其他DataNode读取该副本,并向NameNode报告该信息。

对于文件的读取,NameNode负责引导客户端到最合适的DataNode,由客户端直接连接DataNode去读取数据。这种设计可以让数据的I/O任务分散在所有DataNode上,也有利于HDFS扩展到更大规模的客户端进行并行处理;同时NameNode只需提供请求数据块所在的位置信息,而不需要通过它提供数据,避免了NameNode随着客户端数量的增长而成为系统的瓶颈。

发表评论

后才能评论