Hadoop源码解析之Configuration简介

       对配置文件的配置及解析是每个框架的基本且必不可少的部分,本文主要对Hadoop中的配置文件的解析类Configuration的基本结构及主要方法进行介绍。       Hadoop的配置文件的操作主要分为三个部分:配置的加载、属性读取和设置,本文将分别对其进行介绍。如下是Configuration的主要的成员属性:

/** 
  * 保存了所有的资源配置的来源信息,资源文件主要有以下几种形式: URL、String、Path、InputStream和Properties。
  */
private ArrayList<Resource> resources = new ArrayList<Resource>();

/**
  * 记录了配置文件中配置的final类型的属性名称,标记为final之后如果另外有同名的属性,那么该属性将不会被替换
  */
private Set<String> finalParameters = Collections.newSetFromMap(new ConcurrentHashMap<String, Boolean>());

/**
  * 记录了配置初始化后更新过的属性,其键为更新的属性名,值为更新操作的来源
  */
private Map<String, String[]> updatingResource;

/**
  * 记录了所有的属性,包括系统初始化以及后续设置的属性
  */
private Properties properties;

/**
  * 记录了除了初始化之后手动调用set方法设置的属性
  */
private Properties overlay;

/**
  * 记录了过期的属性
  */
private static AtomicReference<DeprecationContext> deprecationContext = new AtomicReference<DeprecationContext>(new DeprecationContext(null, defaultDeprecations));

1.配置的加载

       Configuration中的配置文件的信息主要保存在resources属性中,该属性是一个ArrayList<Resource>类型,如下是Resource的结构:

private static class Resource {
    private final Object resource;
    private final String name;
    
    // 构造方法,get和set方法略
  }

这里的name表示资源文件的名称,resource则表示具体的资源,其用一个Object类型,但具体的类型如下:

  • URL: 通过一个URL链接来进行读取;
  • String: 从当前classpath下该字符串所指定的文件读取;
  • Path: 以绝对路径指定的配置文件或者是使用url指定的配置;
  • InputStream: 以流的形式指定的配置文件;
  • Properties: 以属性配置类保存的配置信息。 除了可以通过上述方式进行配置的设置以外,Hadoop还设置了几个默认的配置文件:core-default.xml、core-site.xml和hadoop-site.xml,具体的读取代码如下:
  static {
    // Add default resources
    addDefaultResource("core-default.xml");
    addDefaultResource("core-site.xml");

    // print deprecation warning if hadoop-site.xml is found in classpath
    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");
    }
  }

这里需要注意的是,Hadoop对配置文件的读取并不是在Configuration类初始化时进行的,而是在获取配置信息时再进行读取,再此之前,配置相关的信息都保存在resources属性中。如下是addDefaultResource(String)方法的代码:

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

       从上述代码可以看出,在添加配置文件时,其先检查默认配置文件中是否有该配置文件,如果不存在,则将其添加到defaultResources列表中,并且其会对Configuration配置项进行检查,如果其配置了加载默认配置文件,那么其就会对该配置中保存配置信息的properties和finalParameters进行清空,以此触发属性的重新加载。        在初始化时将相关配置信息添加到resources和defaultResources列表之后,配置文件中属性的读取是在客户端具体调用get*方法时进行的,以下是初始化配置信息的代码:

  protected synchronized Properties getProps() {
    if (properties == null) {
      properties = new Properties();
      Map<String, String[]> backup =
          new ConcurrentHashMap<String, String[]>(updatingResource);
      loadResources(properties, resources, quietmode);

      if (overlay != null) {
        properties.putAll(overlay);
        for (Map.Entry<Object,Object> item: overlay.entrySet()) {
          String key = (String)item.getKey();
          String[] source = backup.get(key);
          if(source != null) {
            updatingResource.put(key, source);
          }
        }
      }
    }
    return properties;
  }

上述代码中,首先判断properties是否为空,为空则进行初始化,否则直接返回,这也就是前面为什么将properties和finalParameters进行清空之后能够触发属性的重新加载的原因。在初始化配置信息的时候首先对更新的资源过的资源进行备份,然后调用loadResources()方法加载配置文件的信息,加载完之后还会将用户调用set*方法设置的属性(保存在overlay中)添加到properties中,并且将用户设置的信息添加到updatingResource中。如下是loadResources()方法的具体代码:

  private void loadResources(Properties properties, ArrayList<Resource> resources, boolean quiet) {
    if(loadDefaults) {
      for (String resource : defaultResources) {
        loadResource(properties, new Resource(resource), quiet);
      }
    }
    
    for (int i = 0; i < resources.size(); i++) {
      Resource ret = loadResource(properties, resources.get(i), quiet);
      if (ret != null) {
        resources.set(i, ret);
      
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值