1.客户端会调用DistributedFileSystem对象的create(filePath)方法,与NameNode进行RPC通信。
2.NameNode接收到用户的写文件的RPC请求后,首先进行各种检查。如用户是否有创建权限和该文件是否已存在,检查通过后才会创建一个文件,并将操作记录到editlog中,然后DistributedFileSystem会将DFSOutputStream对象包装在FSDataOutStream实例中,返回客户端;否则文件创建失败并且给客户端抛IOException。
3.客户端会开始写文件,FSOutputStream会将文件进行切块。然后向NameNode请求适合存放文件块的DataNode列表,然后这些DataNode会生成一个数据流管道,我们假设副本集参数被设置为3,那么这个数据流管道中就有三个DataNode节点。
4.首先FSOutputStream会将文件块向数据流管道中的第一个DataNode节点写数据,第一个DataNode接收文件块后会把文件块写向数据流管道中的第二个节点,同理,第二个节点接收保存数据块后会将数据块写向数据流管道中的第三个DataNode节点。
5.当第三各DataNode节点数据库写入成功后,会向第二个DataNode节点发送数据写入成功的确认消息,第二个DataNode节点收到第三个的确认消息后会向第一个DataNode节点发送数据写入成功的确认消息。当三个节点都确认数据写入成功后DataNode会向FSOutputStream对象发送ack packets,最后会调用对象的close()方法。
注意:假如客户端就是集群中某一个DataNode节点,那么第一个数据块会优先存储在本DataNode节点上。
3.文件的读流程
1、客户端会调用DistributedFileSystem的open()方法与NameNode进行RPC通信,NameNode会返回该文件的部分或全部的block列表
(也包含该列表各block的分布在Datanode地址的列表),也就是返回FSDataInputStream对象
2、客户端调用FSDataInputStream对象的read()方法
a、会去与第一个块的最近的datanode进行read,读取完后,会check,假如successful,会关闭 与当前 Datanode通信;
(假如check fail,会记录失败的块+Datanode信息,下次就不会读取;那么会去该块的第二个 Datanode地址读取)
b、然后去第二个块的最近的Datanode上的进行读取,check后,会关闭与此datanode的通信。
c、假如block列表读取完了,文件还未结束,那么FileSystem会从Namenode获取下一批的block的列表。
(当然读操作对于Client端是透明的)
3、客户端将文件块读取完整后,会调用FSDataInputStream的close()方法,关闭输入流。