hadoop FileSystem源码分析

* FileSystem是Hadoop下一个抽象的文件系统,其有许多具体的实现类,如hdfs对应的分布式文件系统DistributedFileSystem、FTP对应的FTPFileSystem,以及本地文件系统对应的LocalFileSystem等。现在通过一个简单的文件系统初始化的代码分析构建FileSystem的源码。

1、简单的fs初始化代码:

   public static void init() throws IOException{
        Configuration conf = new Configuration();
        conf.set("fs.defaultFS", "hdfs://master:9000/");
        fs=FileSystem.get(conf);

    }

首先只设置了conf,里面只配置了“fs.defaultFS”这一选项,设置为hdfs 下面看FileSystem.get(conf)

2、FileSystem.get(conf)

  public static FileSystem get(Configuration conf) throws IOException {
    return get(getDefaultUri(conf), conf);
  }

这个方法只是调用了get方法,其中第一个参数是由conf构造出得到的uri,如“hdfs://master:9000/”

3、public static FileSystem get(URI uri, Configuration conf)

由图中看出,首先从uri中读出文件系统类别schema和主机名authorty,这里是hdfs与master:9000 ,如果为空则使用默认的本地文件系统,随后通过conf.getBoolean(disableCacheName, false)查看是否禁用缓存,如果禁用则新建一个fs,否则从CACHE中get

4、CACHE.get(uri,conf)

  FileSystem get(URI uri, Configuration conf) throws IOException{
      Key key = new Key(uri, conf);
      return getInternal(uri, conf, key);
    }

通过uri和conf构造一个Key,随后调用getInternal方法

5、getInternal(uri, conf, key)


首先根据从之前生成的key看是否缓存map中存在缓存,如果存在,则返回map中的,否则调用createFileSystem(uri, conf)生成新的
然后将生成的fs实例插入到map中,以便下次缓存

6、createFileSystem(uri, conf)

  private static FileSystem createFileSystem(URI uri, Configuration conf
      ) throws IOException {
    Class<?> clazz = getFileSystemClass(uri.getScheme(), conf);
    FileSystem fs = (FileSystem)ReflectionUtils.newInstance(clazz, conf);
    fs.initialize(uri, conf);
    return fs;
  }

首先通过scheme与conf确定反设的类实例,这里的scheme是hdfs,因此反射的是DistributedFileSystem类,随后通过一个工具类ReflectionUtils构建实例,然后调用initialize方法进行类成员的初始化

7、fs.initialize(uri, conf);


查看DistributedFileSystem的initialize方法可以发现,此方法用于初始化各个成员,例如host、conf、工作目录以及客户端dfs的初始化。这里重点关注dfs的构造方法new DFSClient(uri, conf, statistics);

8、new DFSClient(uri, conf, statistics);

  /**
   * Same as this(nameNodeUri, null, conf, stats);
   * @see #DFSClient(URI, ClientProtocol, Configuration, FileSystem.Statistics) 
   */
  public DFSClient(URI nameNodeUri, Configuration conf,
                   FileSystem.Statistics stats)
    throws IOException {
    this(nameNodeUri, null, conf, stats);
  }

从注释看出,等同于调用四个参数的构造函数,其中第二个参数为null

9、public DFSClient(URI nameNodeUri, ClientProtocol rpcNamenode, Configuration conf, FileSystem.Statistics stats)




这里仍然是对成员赋值,NameNodeProxies.createProxyWithLossyRetryHandler方法可以返回一个代理,当集群式不是HA(高可用)模式时,此方法返回Null。 由于配置中没有配置高可用,于是通过 NameNodeProxies.createProxy(conf, nameNodeUri,
ClientProtocol.class, nnFallbackToSimpleAuth)方法通过roc操作生成namenode的代理。生成后再为dtService与nameNode赋值

扫描二维码关注公众号,回复: 1028976 查看本文章

10 、createProxy(Configuration conf,URI nameNodeUri, Class xface, AtomicBoolean fallbackToSimpleAuth)


这里的生成代理分为高可用情况以及非高可用情况,由于是non-HA的情况,调用createNonHAProxy(…)方法

11、createNonHAProxy(conf, NameNode.getAddress(nameNodeUri), xface,UserGroupInformation.getCurrentUser(), true, fallbackToSimpleAuth)


这里根据不同的xface生成不同的业务接口,默认是使用createNNProxyWithClientProtocol(…)方法创建客户端代理接口

12、createNNProxyWithClientProtocol(…)


从图中可看出是通过RPC的方式生成了namenode代理。此时客户端即可通过rpc操作调用namenode的相关操作。至此成员初始化完成。可以进行相关的hdfs的操作

猜你喜欢

转载自blog.csdn.net/phn_csdn/article/details/72901174
今日推荐