Hhadoop-2.7.0中HDFS写文件源码分析(二):客户端实现(1)

一、综述      HDFS写文件是整个Hadoop中最为复杂的流程之一,它涉及到HDFS中NameNode、DataNode、DFSClient等众多角色的分工与合作。      首先上一段代码,客户端是如何写文件的:Configuration conf = new Configuration();FileSystem fs = FileSystem.get(conf);Path file
摘要由CSDN通过智能技术生成

一、综述

      HDFS写文件是整个Hadoop中最为复杂的流程之一,它涉及到HDFS中NameNode、DataNode、DFSClient等众多角色的分工与合作。

      首先上一段代码,客户端是如何写文件的:

Configuration conf = new Configuration();
FileSystem fs = FileSystem.get(conf);
Path file = new Path("demo.txt");
FSDataOutputStream outStream = fs.create(file);
out.write("Welcome to HDFS Java API !!!".getBytes("UTF-8")); 
outStream.close();
      只有简单的6行代码,客户端封装的如此简洁,各组件间的RPC调用、异常处理、容错等均对客户端透明。

      总体来说,最简单的HDFS写文件大体流程如下:

      1、客户端获取文件系统实例FileSyStem,并通过其create()方法获取文件系统输出流outputStream;

            1.1、首先会联系名字节点NameNode,通过ClientProtocol.create()RPC调用,在名字节点上创建文件元数据,并获取文件状态FileStatus;

            1.2、通过文件状态FileStatus构造文件系统输出流outputStream;

      2、通过文件系统输出流outputStream写入数据;

             2.1、首次写入会首先向名字节点申请数据块,名字节点能够掌握集群DataNode整体状况,分配数据块后,连同DataNode列表信息返回给客户端;

             2.2、客户端采用流式管道的方式写入数据节点列表中的第一个DataNode,并由列表中的前一个DataNode将数据转发给后面一个DataNode;

             2.3、确认数据包由DataNode经过管道依次返回给上游DataNode和客户端;

             2.4、写满一个数据块后,向名字节点提交一个数据;

             2.5、再次重复2.1-2.4过程;

      3、向名字节点提交文件(complete file),即告知名字节点文件已写完,然后关闭文件系统输出流outputStream等释放资源。


      可以看出,在不考虑异常等的情况下,上述过程还是比较复杂的。本文,我将着重阐述下HDFS写数据时,客户端是如何实现的,关于NameNode、DataNode等的配合等,后续文章将陆续推出,敬请关注!

二、实现分析

      我们将带着以下问题来分析客户端写入数据过程:

      1、如何获取数据输出流?

      2、如何通过数据输出流写入数据?

      3、数据输出流关闭时都做了什么?

      4、如果发生异常怎么办?即如何容错?


      (一)如何获取数据输出流?

      HDFS客户端获取数据流是一个复杂的过程,流程图如下:


      

      以DistributedFileSystem为例,create()是其入口方法,DistributedFileSystem内部封装了一个DFS的客户端,如下:

  DFSClient dfs;
      在DistributedFileSystem的初始化方法initialize()中,会构造这个文件系统客户端,如下:

    this.dfs = new DFSClient(uri, conf, statistics);

      而create()方法就是通过这个文件系统客户端dfs获取数据输出流的,如下:

  @Override
  public FSDataOutputStream create(final Path f, final FsPermission permission,
    final EnumSet<CreateFlag> cflags, final int bufferSize,
    final short replication, final long blockSize, final Progressable progress,
    final ChecksumOpt checksumOpt) throws IOException {
    statistics.incrementWriteOps(1);
    Path absF = fixRelativePart(f);
    return new FileSystemLinkResolver<FSDataOutputStream>() {
      
      /*
       * 创建文件系统数据输出流
       */
      @Override
      public FSDataOutputStream doCall(final Path p)
          throws IOException, UnresolvedLinkException {
        
    	// 调用create()方法创建文件,并获取文件系统输出流  
    	final DFSOutputStream dfsos = dfs.create(getPathName(p), permission,
                cflags, replication, blockSize, progress, bufferSize,
      
  • 4
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值