接下来我们分析一下数据的读流程
1. 由DistributedFileSystem::read的实现可知,读数据实际是调用DFSClient::DFSDataInputStream的read函数,DFSDataInputStream是DFSInputStream的一个wrapper,所以实际调用的是DFSInputStream的read函数
2. read函数首先会判断当前文件偏移pos是否超过当前再读的block的末尾,如果是则调用blockSeekTo(pos)
a. 首先关闭当前的blockReader和socket连接
b. 调用getBlockAt(target),根据指定的偏移pos获取对应的block
i. 如果客户端没有缓存对应的LocatedBlock,则调用namenode.getBlockLocations(src, start, length),再取10个block缓存在client
c. 调用chooseDataNode(targetBlock),根据获得目标块targetBlock,选取一个Datanode
i. 从targetBlock中获取块存在的datanode列表,选取一个最佳的连接(调用bestNode方法)
1) namenode在返回给客户端时,就已经对每个block对应的datanode按优先级做了排序
ii. 如果连接不上,则把当前的datanode加入deadnodes列表,然后尝试连接下一个
d. 重新建立blockReader和socket连接
建立好socket后,client会想datanode发送请求,协议如下: