设为首页 加入收藏

TOP

Hadoop HDFS FileSystem详解
2019-03-05 00:19:40 】 浏览:133
Tags:Hadoop HDFS FileSystem 详解

背景介绍

Hadoop实现了一套分布式文件系统HDFS,当使用Hadoop的API进行开发,使用HDFS文件系统的时候,必定会用到Hadoop中的FileSystem抽象类,通过FileSystem类的get的方法获取FileSystem的实例,并通过该实例来进行文件系统的操作。

FileSystem fs = FileSystem.get(cfg);

对于该场景,我们可能会有如下疑问:

  1. FileSystem是一个抽象类,那用来HDFS文件系统的具体实现类是哪一个呢?
  2. 通过FileSystem的get方法,是如何获取到HDFS文件系统实例的呢?
  3. Hadoop并不仅支持HDFS文件系统,还支持非常多样的第三方文件系统,如:Amazon S3,当使用这些第三方文件系统的时候,也是用同样的方法来获取文件系统实例的,FileSystem是如何做到的呢?

接下来将一一讲解这些问题。

问题分析

首先看一下FileSystem类的get方法具体实现:

  /**
   * Returns the configured filesystem implementation.
   * @param conf the configuration to use
   */
  public static FileSystem get(Configuration conf) throws IOException {
    return get(getDefaultUri(conf), conf);
  }
  
  /** Get the default filesystem URI from a configuration.
   * @param conf the configuration to use
   * @return the uri of the default filesystem
   */
  public static URI getDefaultUri(Configuration conf) {
    return URI.create(fixName(conf.get(FS_DEFAULT_NAME_KEY, DEFAULT_FS)));
  }

该静态方法首先从配置文件中读取了URI信息,并调用了另一个异构get方法。如果是使用HDFS文件系统,其URI为hdfs://;如果没有配置,默认使用的是本地文件系统,URI为:file://。

  /** Returns the FileSystem for this URI's scheme and authority.  The scheme
   * of the URI determines a configuration property name,
   * <tt>fs.<i>scheme</i>.class</tt> whose value names the FileSystem class.
   * The entire URI is passed to the FileSystem instance's initialize method.
   */
  public static FileSystem get(URI uri, Configuration conf) throws IOException {
    String scheme = uri.getScheme();
    String authority = uri.getAuthority();

    if (scheme == null && authority == null) {     // use default FS
      return get(conf);
    }

    if (scheme != null && authority == null) {     // no authority
      URI defaultUri = getDefaultUri(conf);
      if (scheme.equals(defaultUri.getScheme())    // if scheme matches default
          && defaultUri.getAuthority() != null) {  // & default has authority
        return get(defaultUri, conf);              // return default
      }
    }
    
    String disableCacheName = String.format("fs.%s.impl.disable.cache", scheme);
    if (conf.getBoolean(disableCacheName, false)) {
      return createFileSystem(uri, conf);
    }

    return CACHE.get(uri, conf);
  }

这个get方法判断了是否配置了FileSystem实例的缓存功能。如果配置为true,当使用get获取实例的时候,如果先前创建的实例还可用,则使用已经存在的实例,而不进行重新创建。

接下来我们直接看创建实例的方法,不对cache功能进行深入分析。createFileSystem方法如下:

  private static FileSystem createFileSystem(URI uri, Configuration conf
      ) throws IOException {
    Class<> clazz = getFileSystemClass(uri.getScheme(), conf);
    if (clazz == null) {
      throw new IOException("No FileSystem for scheme: " + uri.getScheme());
    }
    FileSystem fs = (FileSystem)ReflectionUtils.newInstance(clazz, conf);
    fs.initialize(uri, conf);
    return fs;
  }
该方法首先通过URI的前缀获取了URI中描述的文件系统的具体实现类,然后通过反射机制创建出FileSystem的实例。

接下来看下getFileSystemClass方法的实现,查看如何通过URI前缀获取相应文件系统的具体实现类。

  public static Class< extends FileSystem> getFileSystemClass(String scheme,
      Configuration conf) throws IOException {
    if (!FILE_SYSTEMS_LOADED) {
      loadFileSystems();
    }
    Class< extends FileSystem> clazz = null;
    if (conf != null) {
      clazz = (Class< extends FileSystem>) conf.getClass("fs." + scheme + ".impl", null);
    }
    if (clazz == null) {
      clazz = SERVICE_FILE_SYSTEMS.get(scheme);
    }
    if (clazz == null) {
      throw new IOException("No FileSystem for scheme: " + scheme);
    }
    return clazz;
  }

该方法首先判断了file system是否已经加载,如果未加载,则加载file system相关的信息。具体加载内容如下:

  private static void loadFileSystems() {
    synchronized (FileSystem.class) {
      if (!FILE_SYSTEMS_LOADED) {
        ServiceLoader<FileSystem> serviceLoader = ServiceLoader.load(FileSystem.class);
        for (FileSystem fs : serviceLoader) {
          SERVICE_FILE_SYSTEMS.put(fs.getScheme(), fs.getClass());
        }
        FILE_SYSTEMS_LOADED = true;
      }
    }
  }
这里通过了Java中的ServiceLoader加载了FileSystem的服务,所谓的FileSystem服务就是实现了FileSystem抽象类的具体实现类,具体ServiceLoader的相关介绍请看ServiceLoader详解

通过ServiceLoader,把META-INF/services中描述的FileSystem服务的具体实现类加载进来了,并获取各个类的前缀和类,从而使得在getFileSystemClass方法中通过URI前缀,获取相应的实现类,并返回去创建相应实例。

通过以上的几个主要的方法,Hadoop把文件系统进行了抽象,提供给用户统一的接口进行文件系统的操作,另外也提供了统一的实现方式,可以更方便的集成第三方的文件系统。

】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇HDFS NameNode Ha切换出错 下一篇flume1.8远程写hdfs+hadoop2.8集成

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目