1client向namenode请求block所在的datanode节点列表;
2client从最近位置逐个依次从datanode中读取block信息;
3整个通过io流读取的过程需要校验每个快信息;
4读取完成,关闭所有流。
首先调用FileSystem的open方法获取一个DistributedFileSystem实例;
然后DistributedFileSystem实例通过RPC在NameNode里获得文件的第一批block的locations(可能是需要读取文件的全部,也可能是一部分),同一个block会按照在DataNode的重复数返回多个locations;
返回的多个locations会按照Hadoop拓扑结构排序,按照就近原则来排序;
前面三步结束后会返回一个FSDataInputStream对象,通过调用read方法时,该对象会找出离客户端最近的DataNode并与之建立连接;
数据通过io流从DataNode源源不断地流向客户端;
如果第一个block块数据读取完成,就会关闭指向第一个block块的DataNode连接,接着读取下一个block块,直到把这一批的block块数据读取完成;
每读取完一个block块都会进行checksum验证(校验每个块的信息通过偏移量和预写值对比,写的时候是校验packet的信息),如果读取 DataNode 时出现错误,客户端会 通知 NameNode,然后再从下一个拥有该 block 拷贝的 DataNode 继续读;
如果第一批blocks读取完成,且文件读取还没有结束,也就是文件还没读完。FSDataInputStream就会向NameNode获取下一批blocks的locations,然后重复上面的步骤,直到所有blocks读取完成,这时就会关闭所有的流。