栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

Hadoop Configuration 类加载属性解析

Hadoop Configuration 类加载属性解析

文章目录
  • Hadoop Configuration 类加载属性解析
    • 1. 疑问
      • 1.1. 结论
    • 2. 从源码中一探究竟
      • 2.1. `new Configuration()`时发生了什么
      • 2.2. `configuration.get("fs.defaultFS")`时发生了什么

Hadoop Configuration 类加载属性解析

以下过程在3.2.2版本的源码上分析

1. 疑问

当我们创建HDFS client时,最简单的做法如下:

Configuration configuration = new Configuration();
FileSystem fileSystem = FileSystem.get(configuration);

然后即可通过fileSystem对象来操作相应的API。
FileSystem实例从Configuration实例中获取HDFS相应配置,那么Configuration是如何获取HDFS的相关配置项呢?

当我们未手动将hadoop相关配置文件放置到classpath中时,直接执行如下代码,控制台打印file:///,get()时,从哪里获取默认配置值,发生了什么?

Configuration configuration = new Configuration();
String s = configuration.get("fs.defaultFS");
System.out.println(s); // 打印file:///
1.1. 结论

直接上结论。在创建Hadoop(HDFS、Yarn、MR)相应客户端时,想要正确加载所需环境属性配置,需要按以下操作:

  1. 将core-site.xml文件放置到classpath路径中(必选)。
    默认情况下,classpath中的hadoop-common-3.2.2.jar中有core-default.xml文件,因此当未手动将core-site.xml文件放置到classpath中时,默认是从core-default.xml文件中加载默认属性,当把core-site.xml文件放置到classpath中,会覆盖core-default.xml中的默认属性值
  2. 请勿将hadoop-site.xml文件放置到classpath路径中。
    否则在执行代码时,会得到DEPRECATED: hadoop-site.xml found in the classpath.相应的日志告警。
  3. 如果创建HDFS Client,将hdfs-site.xml文件放置到classpath路径中。
  4. 如果创建Yarn Client,将yarn-site.xml文件放置到classpath路径中
  5. 如果创建MR Client,将yarn-site.xml文件放置到classpath路径中

org.apache.hadoop.hdfs.HdfsConfiguration、org.apache.hadoop.yarn.conf.YarnConfiguration、org.apache.hadoop.mapred.JobConf 都继承自 org.apache.hadoop.conf.Configuration类,
其中实例化org.apache.hadoop.hdfs.HdfsConfiguration时会将hdfs-default.xml和hdfs-site.xml文件添加到默认配置文件中。
实例化org.apache.hadoop.yarn.conf.YarnConfiguration时会将yarn-default.xml和yarn-site.xml文件添加到默认配置文件中。
实例化org.apache.hadoop.mapred.JobConf时会将mapred-default.xml、mapred-site.xml、yarn-default.xml和yarn-site.xml文件添加到默认配置文件中。

2. 从源码中一探究竟 2.1. new Configuration()时发生了什么
Configuration configuration = new Configuration();

当使用如上方式实例化configuration时,首先加载Configuration类中的static属性和代码块,

实例化static属性
主要依次实例化了如下属性

  
  private static final WeakHashMap REGISTRY = 
    new WeakHashMap();

  
  private static final CopyOnWriteArrayList defaultResources =
    new CopyOnWriteArrayList();

  
  private static DeprecationDelta[] defaultDeprecations = 
    new DeprecationDelta[] {
      new DeprecationDelta("topology.script.file.name", 
        CommonConfigurationKeys.NET_TOPOLOGY_script_FILE_NAME_KEY),
      new DeprecationDelta("topology.script.number.args", 
        CommonConfigurationKeys.NET_TOPOLOGY_script_NUMBER_ARGS_KEY),
      new DeprecationDelta("hadoop.configured.node.mapping", 
        CommonConfigurationKeys.NET_TOPOLOGY_CONFIGURED_NODE_MAPPING_KEY),
      new DeprecationDelta("topology.node.switch.mapping.impl", 
        CommonConfigurationKeys.NET_TOPOLOGY_NODE_SWITCH_MAPPING_IMPL_KEY),
      new DeprecationDelta("dfs.df.interval", 
        CommonConfigurationKeys.FS_DF_INTERVAL_KEY),
      new DeprecationDelta("fs.default.name", 
        CommonConfigurationKeys.FS_DEFAULT_NAME_KEY),
      new DeprecationDelta("dfs.umaskmode",
        CommonConfigurationKeys.FS_PERMISSIONS_UMASK_KEY),
      new DeprecationDelta("dfs.nfs.exports.allowed.hosts",
          CommonConfigurationKeys.NFS_EXPORTS_ALLOWED_HOSTS_KEY)
    };

  
  private static AtomicReference deprecationContext =
      new AtomicReference(
          new DeprecationContext(null, defaultDeprecations));

执行static代码块
该静态代码块中,主要作用为使用org.apache.hadoop.conf.Configuration#addDefaultResource方法给上面实例化的defaultResources集合添加元素,将core-default.xm、core-site.xml和hadoop-site.xml(classpath存在的情况下)文件名称添加到集合中。

!!! note “”
从static代码块中即可看出,默认使用的属性配置文件为core-default.xml、core-site.xml和hadoop-site.xml。
在/org/apache/hadoop/hadoop-common/3.2.2/hadoop-common-3.2.2.jar中默认带有了core-default.xml配置文件。

static {
   // Add default resources
   // 将core-default.xml和core-site.xml文件名添加到上面实例化的defaultResources集合中
   addDefaultResource("core-default.xml");
   addDefaultResource("core-site.xml");

   // print deprecation warning if hadoop-site.xml is found in classpath
   // 如果在classpath中找到了hadoop-site.xml文件,则打印告警信息,并将hadoop-site.xml文件名添加到defaultResources集合中
   ClassLoader cL = Thread.currentThread().getContextClassLoader();
   if (cL == null) {
     cL = Configuration.class.getClassLoader();
   }
   if (cL.getResource("hadoop-site.xml") != null) {
     LOG.warn("DEPRECATED: hadoop-site.xml found in the classpath. " +
         "Usage of hadoop-site.xml is deprecated. Instead use core-site.xml, "
         + "mapred-site.xml and hdfs-site.xml to override properties of " +
         "core-default.xml, mapred-default.xml and hdfs-default.xml " +
         "respectively");
     addDefaultResource("hadoop-site.xml");
   }
 }

 
 public static synchronized void addDefaultResource(String name) {
   if(!defaultResources.contains(name)) {
     defaultResources.add(name);
     for(Configuration conf : REGISTRY.keySet()) {
       if(conf.loadDefaults) {
         conf.reloadConfiguration();
       }
     }
   }
 }

调用构造方法完成Configuration的实例化

  public Configuration() {
    this(true);
  }

  
  public Configuration(boolean loadDefaults) {
    this.loadDefaults = loadDefaults;

    synchronized(Configuration.class) {
      // 将实例化的对象放入到REGISTRY集合中
      REGISTRY.put(this, null);
    }
  }
2.2. configuration.get("fs.defaultFS")时发生了什么

回到开头的问题,当我们未手动将hadoop相关配置文件放置到classpath中时,以下代码为什么打印file:///?

Configuration configuration = new Configuration();
String s = configuration.get("fs.defaultFS");
System.out.println(s); // 打印file:///

首先从上述实例化过程中创建的deprecationContext属性中进行弃用属性key和对应新属性key的替换。
然后调用org.apache.hadoop.conf.Configuration#loadProps方法从默认的配置文件中加载相应属性。然后在该方法中调用org.apache.hadoop.conf.Configuration#loadResources加载属性。
关键过程见代码中的注释。

  protected synchronized Properties getProps() {
    if (properties == null) {
      // 将成员属性properties赋值为空,用于存放加载后的属性
      properties = new Properties();
      loadProps(properties, 0, true);
    }
    return properties;
  }

  
  private synchronized void loadProps(final Properties props,
      final int startIdx, final boolean fullReload) {
    if (props != null) {
      // 第一次执行该方法时,backup为null
      Map backup =
          updatingResource != null
              ? new ConcurrentHashMap<>(updatingResource) : null;
      // 从此处开始真正的从配置文件中加载属性
      // 加载属性,初始时props为空,resources为空,startIdx为0,fullReload为true
      loadResources(props, resources, startIdx, fullReload, quietmode);
      // 初始时,overlay不为null,但是为空
      if (overlay != null) {
        props.putAll(overlay);
        if (backup != null) {
          for (Map.Entry item : overlay.entrySet()) {
            String key = (String) item.getKey();
            String[] source = backup.get(key);
            if (source != null) {
              updatingResource.put(key, source);
            }
          }
        }
      }
    }
  }

  // 遍历配置文件并从配置文件加载属性到properties中
  private void loadResources(Properties properties,
                             ArrayList resources,
                             int startIdx,
                             boolean fullReload,
                             boolean quiet) {
    if(loadDefaults && fullReload) {
      // 按顺序加载配置文件中的属性,因此core-default.xml、core-site.xml和hadoop-site.xml中的属性会依次进行覆盖
      for (String resource : defaultResources) {
        loadResource(properties, new Resource(resource, false), quiet);
      }
    }
    
    for (int i = startIdx; i < resources.size(); i++) {
      Resource ret = loadResource(properties, resources.get(i), quiet);
      if (ret != null) {
        resources.set(i, ret);
      }
    }
    this.addTags(properties);
  }

  
  private Resource loadResource(Properties properties,
                                Resource wrapper, boolean quiet) {
    String name = UNKNOWN_RESOURCE;
    try {
      Object resource = wrapper.getResource();
      name = wrapper.getName();
      boolean returnCachedProperties = false;

      // Resource类未继承任何父类,因此并不满足以下的逻辑判断
      if (resource instanceof InputStream) {
        returnCachedProperties = true;
      } else if (resource instanceof Properties) {
        overlay(properties, (Properties)resource);
      }

      // 从文件中真正的读取属性值,由于Resource未继承任何父类,因此从classpath中加载配置文件。 
      // 如果没有手动给classpath中添加core-default.xml、core-site.xml文件,会从/org/apache/hadoop/hadoop-common/3.2.2/hadoop-common-3.2.2.jar!/core-default.xml位置读取配置文件
      XMLStreamReader2 reader = getStreamReader(wrapper, quiet);
      if (reader == null) {
        if (quiet) {
          return null;
        }
        throw new RuntimeException(resource + " not found");
      }
      Properties toAddTo = properties;
      if(returnCachedProperties) {
        toAddTo = new Properties();
      }

      // 读取到属性值后,将属性值依次赋值到toAddTo
      List items = new Parser(reader, wrapper, quiet).parse();
      for (ParsedItem item : items) {
        loadProperty(toAddTo, item.name, item.key, item.value,
            item.isFinal, item.sources);
      }
      reader.close();

      if (returnCachedProperties) {
        overlay(properties, toAddTo);
        return new Resource(toAddTo, name, wrapper.isParserRestricted());
      }
      return null;
    } catch (IOException e) {
      LOG.error("error parsing conf " + name, e);
      throw new RuntimeException(e);
    } catch (XMLStreamException e) {
      LOG.error("error parsing conf " + name, e);
      throw new RuntimeException(e);
    }
  }
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/682721.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号