1.读取数据
大致流程:client向namenode获取block所在的位置,然后通过FSDataInputStream的read方法是就近的block所在的datanode读取信息,最后关闭.
详细流程:
(1)首先客户端发送请求,并调用fileSystem的open方法获取一个DistributedFileSystem的实例,
(2)然后DistributedFileSystem向namenode申请获取文件各个block快所在的locations(包括副本),
(3)返回的多个locations会按照Hadoop拓扑结构排序,按照就近原则来排序,
(4)此时会返回一个FSDataInputStream对象,通过调用read方法,去找出block离客户端最近的datanode并与之建立连接,通过io将数据传输到客户端
(5)当第一个block数据传输完毕后,关闭连接,开始第二个block数据的传输,依此类推
2.写入数据
大致流程:客户端向namenode发送写入数据请求,namenode检查文件,如果通过就返回输出流对象,然后客户端切分文件并将数据和namenode返回的datanode列表返回到最近的datanode节点中,datanode写完后返回完成信息.数据全部写完后,关闭数据流,并反馈成功信息给namenode
详细流程:
(1)客户端通过configuration类加载配置文件信息,然后调用fileSystem的get方法,获取分布式文件系统对象DistributedFileSystem对象,然后通过这个对象的create方法,向namenode发送写文件的请求
(2)此时namenode开始检查文件,比如所在位置是否已经存在,客户端是否有权限写入等.
(3)检查成功后,namenode会在此位置新建一个文件,初始大小为0,并记录元数据,返回一个FSDataOutputStream输出流对象
(4)FSDataOutputStream封装一个DFSOutputStream对象,来负责处理namenode和datanode的通信
(5)客户端将数据按照设置的block大小和split大小对数据进行切分,通过DFSOutputStream的create方法开始执行写入操作(DFSOutputStream会把数据切成一个个小packet,然后排成队列 dataQueue;
DataStreamer(DFSOutputStream的内部线程类)会去处理dataQueue,它先问询 NameNode 这个新的 block 最适合存储的在哪几个DataNode里,比如重复数是3,那么就找到3个最适合的 DataNode,把它们排成一个 pipeline。DataStreamer 把 packet 按队列输出到管道的第一个 DataNode 的内存中,然后第一个 DataNode又把 packet 输出到第二个 DataNode 中,以此类推)
(6)当第一个block的所有packet都写入完成后,客户端会调用FSDataOutputStream的close方法关闭写入流,并开始下一个block的写入操作,依此类推
(7)当所有的block都写入完成后,客户端会将完成信息告诉namenode,namenode将该文件标记成已完成,此时,写入文件操作已完成