HDFS客户端 输入流源码解析
来源:互联网 发布:js鼠标点击触发事件 编辑:程序博客网 时间:2024/05/16 01:58
1、构造DFSInputStream流
DFSClient构造函数中初始化成员后,从配置{"dfs.namenode.rpc-address"}获取namenode的地址,建立rpc连接。
通过open()打开流,创建DFSInputStream流,调用openInfo()=>fetchLocatedBlocks():其中
LocatedBlocks newInfo = callGetBlockLocations();//向namenode获取文件的所在的地址等信息,默认获取10*64M长度的信息。
调用updateBlockInfo(newInfo),该函数的目的是更新从namenode获取到的block长度,因为datanode收到数据后并不能及时上报到namenode,所以如果文件还处在构建状态,说明namenode端的长度尚未更新。
首先判断该文件时候在构建状态下,然后校验返回的newInfo中的最后一个Block的长度+该Block的startOffset是否等于该文件的长度,是则无需更新,否则建立于最后一个块坐在datanode的RPC连接,并更新newInfo。至此,DFSInputStream构造完毕。
需要注意的是,由于同一个Block在多个datanode上有副本,而此处建立rpc连接是通过与最后的Block所在datanode的其中一个,但是,多个拥有该Block的datanode之间,block的长度不一定一致。
2、读数据
read(byte buf[],int off,int len);
由于客户端读数据可能要跨越多个datanode,读的过程中需要用一个标志pos记录读取的长度,以便判断下一个要读取的数据在说明位置。
该方法中currentNode用于记录当前读的数据的节点,它根据pos的值,调用blockSeekTo(pos)获取。
获取currentNode后,调用readBuffer()读取数据。不断循环直到需要的长度为止。
blockSeekTo(pos):
(1) 首先调用getBlockAt(),该方法根据参数offset的值,返回需要读取的locateBlock。内部实现首先从open时cache住的locatedBlocks查找,找不到则重新调用namenode的 rpc方法获取locatedBlocks,并将这些信息插入cache中,方便下次查找。返回本次需要读取的locatedBlock.
此处查找通过Collections.binarySearch,即二分查找。相关资料见博文 “Collections 二分查找”
(2) 通过chooseDataNode,选择不死的DN。建立TCP连接,构造blockReader对象,用于真正读取数据。如果连接失败,则重新获取其他DN的连接。此处有一点,如果需要读取的源为本地,即DFSClient与读取源在同一机器上,并且文件不在构建中,可以构建本地blockReader对象,该构造函数中,发送流式接口请求包并等待应答。由于校验的需要,数据节点有时会多发送一些数据,实际应答数据开始位置从该socket输入流读取并保存到变量firstChunkOffset中,客户端从该DN需要读取流的开始位置保存到startOffset中。至此,blockSeekTo完成使命。
readBuffer():
(1) 调用BlockReader的read函数。如果在读的过程中发生校验失败,说明此dn上的数据有损坏,需要向namenode报坏块,并重新选择其他的DN建立连接。如果发生IO失败,需要在同一个DN上尝试多次。
(2) 先判断是否头部有多余的数据(可通过前面描述的startOffset和FirstChunkOffset判断),是则跳过这部分数据。然后调用基类FSInputChecker的read函数(后面介绍)。返回后,判断是否已经读入了一次读请求的所有数据,是则调用DN RPC方法告知datanode此数据块正确,以减少datanode扫描器的工作量。
(3) FSInputChecker的read函数:循环调用read1()函数,直到返回需要的长度为止。
(4) read1():调用readChecksumChunk(),此函数调用readChunk()获取一块实际数据及所有校验数据,并对这一块实际数据进行校验。
(5) 由于循环调用read1(),直到所有数据均被读取并校验完毕。至此。客户端的read功能才正确结束。
注:读取所有校验数据时,需要读取多少长度的判断:
调用adjustChecksumBytes(dataLen),此函数根据从socket输入流中获取的dataLen,并根据bytesPerChecksum和checksumSize计算出长度,int requiredSize = ((dataLen + bytesPerChecksum - 1)/bytesPerChecksum) * checksumSize,checksumSize在CRC校验时为4,即512字节有4字节的CRC校验码。
- HDFS客户端 输入流源码解析
- HDFS客户端 输出流源码解析
- Hadoop源码分析之HDFS客户端的输入流类结构
- hadoop源码 - HDFS的文件操作流 写操作(客户端)
- HDFS源码解析(1)---初识HDFS
- HDFS源码分析EditLog之获取编辑日志输入流
- hadoop源码解析之hdfs写数据全流程分析---客户端处理
- Hdfs-源码解析(1)
- Hdfs-源码解析(2)
- Hdfs-源码解析(3)
- HDFS源码解析(一)
- HDFS源码解析(二)
- HDFS源码解析(三)
- ZookeeperNet客户端源码解析
- eureka客户端源码解析
- HDFS追本溯源:HDFS操作的逻辑流程与源码解析
- HDFS追本溯源:HDFS操作的逻辑流程与源码解析
- hadoop源码解析之hdfs内部结构分析
- 144 小珂的苦恼
- 素数
- Hibernate之Criteria
- HDU2588GCD(欧拉函数)
- POJ1037 A decorative fence 【动态规划】
- HDFS客户端 输入流源码解析
- 145 聪明的小珂
- leetcode(十五)Merge Sorted Array
- Oracle 数据泵导出遇到Bug 5472417
- HDOJ-2028(最小公倍数)
- Python的中文编码转换问题
- 创建你自己的 iOS 框架
- hdu4862 2014多校B题/ 费用流(最优情况下用不大于K条路径覆盖)(不同的解法)
- 153 king VS king