Hadoop——Configuration类详解

本文介绍了Hadoop中的Configuration类,详细解析了其内部实现机制及如何使用。Configuration类负责管理Hadoop集群的所有配置信息,支持属性扩展及配置项的覆盖。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转自:http://blog.youkuaiyun.com/ghuilee/article/details/45771003

1.configuration类简介
Hadoop没有使用java.util.Properties管理配置文件,也没有使用Apache Jakarta Commons Configuration管理配置文件,而是使用了一套独有的配置文件管理系统,并提供自己的API,即使用org.apache.hadoop.conf.Configuration处理配置信息。这个类是作业的配置信息类,任何作用的配置信息必须通过Configuration传递,因为通过Configuration可以实现在多个mapper和多个reducer任务之间共享信息。
2.Hadoop配置文件的格式:

<?xml version="1.0"?>   
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>   
<property>  
    <name>dfs.name.dir</name>  
    <value>/home/hdfs/name</value>  
    <description>.......</description>   
    <final>true</final>   
</property>  
<property>  
    <name>dfs.data.dir</name>  
    <value>/home/hdfs/data</value>  
</property>  
</configuration>   

3.configuration类代码:

public class Configuration implements Iterable<Map.Entry<String,String>>,  
                                      Writable {  
  private static final Log LOG =  
    LogFactory.getLog(Configuration.class);  
  
  // 用来设置加载配置的模式。为true(默认值),在加载解析配置文件过程中,不输出日志信息。  
  // quietmode只是一个方便开发人员调试的变量。  
  private boolean quietmode = true;  
    
  // resources用于存储整个XML文件,并不是存键值对,即表明资源列表  
  private ArrayList<Object> resources = new ArrayList<Object>();  
  
  // finalParameters的类型是Set<String>,用来保存所有在配置文件中已经被声明为final的键–值对的键  
  private Set<String> finalParameters = new HashSet<String>();  
    
  // 用于确定是否加载默认资源  
  private boolean loadDefaults = true;  
    
  private static final WeakHashMap<Configuration,Object> REGISTRY =   
    new WeakHashMap<Configuration,Object>();  
    
  // 存放默认添加的XML文件资源  
  private static final CopyOnWriteArrayList<String> defaultResources =  
    new CopyOnWriteArrayList<String>();  
  static{  
    addDefaultResource("core-default.xml");  
    addDefaultResource("core-site.xml");  
  }  
    
  // 配置文件解析后的键–值对,都存放在properties中,即用来存储加载出来的属性  
  private Properties properties;      
  // 变量overlay用于记录通过set()方式改变的配置项。即出现在overlay中的键–值对是应用设置的,而不是通过对配置资源解析得到的。  
  private Properties overlay;  
  // 类加载器变量,可以通过它来加载指定类,也可以通过它加载相关的资源    
  private ClassLoader classLoader;  
  {  
    classLoader = Thread.currentThread().getContextClassLoader();  
    if (classLoader == null) {  
      classLoader = Configuration.class.getClassLoader();  
    }  
  }  
    
  
  public Configuration() {  
    this(true);  
  }  
  public Configuration(boolean loadDefaults) {  
  }  
  public Configuration(Configuration other) {  
  }  
    
  /************************************************/  
  /**********向resources中添加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();  
        }  
      }  
    }  
  }  
  // 添加XML文件,在add完成XML文件的时候,不会去更新属性列表的,  
  // 只有当有需要读取属性值的时候才会进行资源的加载。  
  // 要注意的是,在addResource()的时候,会将给定的资源放到一个资源resources里面  
  public void addResource(Path file) {  
    addResourceObject(file);  
  }  
  // 添加资源,输入参数为XML文件名  
  public void addResource(String name) {  
    addResourceObject(name);  
  }  
  public void addResource(URL url) {  
    addResourceObject(url);  
  }  
  public void addResource(InputStream in) {  
    addResourceObject(in);  
  }  
  private synchronized void addResourceObject(Object resource) {  
    resources.add(resource);    // XML添加到resources中  
    reloadConfiguration();  
  }  
  // 重新加载配置  
  public synchronized void reloadConfiguration() {  
    properties = null;                  // 清除之前加载进来的全部属性  
    finalParameters.clear();            // 因为可在属性里面标注final属性,这里将全部final属性清除掉。  
  }  
    
  
  /************************************************/  
  /*********通过属性name获得其对应的值*************/  
  /************************************************/  
    
  // 返回属性name对应的值  
  public String get(String name) {  
    return substituteVars(getProps().getProperty(name));  
  }  
  public String getRaw(String name) {  
    return getProps().getProperty(name);  
  }  
  // return property value, or defaultValue if the property doesn't exist.                      
  public String get(String name, String defaultValue) {  
    return substituteVars(getProps().getProperty(name, defaultValue));  
  }  
  // return property value as an int, or defaultValue.   
  public int getInt(String name, int defaultValue) {  
    String valueString = get(name);  
    if (valueString == null)  
      return defaultValue;  
    try {  
      String hexString = getHexDigits(valueString);  
      if (hexString != null) {  
        return Integer.parseInt(hexString, 16);  
      }  
      return Integer.parseInt(valueString);  
    } catch (NumberFormatException e) {  
      return defaultValue;  
    }  
  }  
  public long getLong(String name, long defaultValue) {  
  }  
  public float getFloat(String name, float defaultValue) {  
  }  
  public boolean getBoolean(String name, boolean defaultValue) {  
  }  
  public Collection<String> getStringCollection(String name) {  
    String valueString = get(name);  
    return StringUtils.getStringCollection(valueString);  
  }  
  public String[] getStrings(String name) {  
    String valueString = get(name);  
    return StringUtils.getStrings(valueString);  
  }  
  public String[] getStrings(String name, String... defaultValue) {  
  }  
  
  /************************************************/  
  /*********通过属性name设置其对应的值*************/  
  /************************************************/  
    
  // 设置属性name对应的值  
  public void set(String name, String value) {  
    getOverlay().setProperty(name, value);  
    getProps().setProperty(name, value);  
  }  
  // 设置不存在的属性name对应的值  
  public void setIfUnset(String name, String value) {  
    if (get(name) == null) {  
      set(name, value);  
    }  
  }  
  // 通过int型设置属性name对应的值  
  public void setInt(String name, int value) {  
    set(name, Integer.toString(value));  
  }  
  public void setLong(String name, long value) {  
    set(name, Long.toString(value));  
  }  
  public void setFloat(String name, float value) {  
    set(name,Float.toString(value));  
  }  
  public void setBoolean(String name, boolean value) {  
    set(name, Boolean.toString(value));  
  }  
  public void setBooleanIfUnset(String name, boolean value) {  
    setIfUnset(name, Boolean.toString(value));  
  }  
  public void setStrings(String name, String... values) {  
    set(name, StringUtils.arrayToString(values));  
  }  
  
  /************************************************************/  
  /*********将resources中的XML资源加载到properties*************/  
  /************************************************************/  
   
  private synchronized Properties getProps() {  
    if (properties == null) {  
      properties = new Properties();  
      // 加载资源  
      loadResources(properties, resources, quietmode);  
      if (overlay!= null)  
        properties.putAll(overlay);  
    }  
    return properties;  
  }  
  private void loadResources(Properties properties,  
                             ArrayList resources,  
                             boolean quiet) {  
    if(loadDefaults) {  
      for (String resource : defaultResources) {  
        loadResource(properties, resource, quiet);  
      }  
      if(getResource("hadoop-site.xml")!=null) {  
        loadResource(properties, "hadoop-site.xml", quiet);  
      }  
    }  
      
    for (Object resource : resources) {  
      loadResource(properties, resource, quiet);  
    }  
  }  
  // 利用java DOM API对resource(XML)进行遍历,将全部的属性值加载到properties  
  private void loadResource(Properties properties, Object name, boolean quiet) {  
        // 部分代码省略  
        
        // Ignore this parameter if it has already been marked as 'final'  
        if (attr != null && value != null) {  
          if (!finalParameters.contains(attr)) {  
            // 添加属性(键值对)  
            properties.setProperty(attr, value);  
            if (finalParameter)  
              finalParameters.add(attr);  
          }  
  }  
  
  /************************************************************/  
  /*********其余方法********************************************/  
  /************************************************************/  
  
  /**  
   * Get the URL for the named resource. 
   * @param name resource name. 
   * @return the url for the named resource. 
   */  
  public URL getResource(String name) {  
    return classLoader.getResource(name);  
  }  
  // Get an input stream attached to the configuration resource with the given name  
  public InputStream getConfResourceAsInputStream(String name) {  
  }  
  public Reader getConfResourceAsReader(String name) {  
  }  
  
  public int size() {  
    return getProps().size();  
  }  
  public void clear() {  
    getProps().clear();  
    getOverlay().clear();  
  }  
  
  /** 
   * Get an Iterator to go through the list of String 
   * key-value pairs in the configuration. 
   * @return an iterator over the entries. 
   */  
  public Iterator<Map.Entry<String, String>> iterator() {  
    // Get a copy of just the string to string pairs. After the old object  
    // methods that allow non-strings to be put into configurations are removed,  
    // we could replace properties with a Map<String,String> and get rid of this  
    // code.  
    Map<String,String> result = new HashMap<String,String>();  
    for(Map.Entry<Object,Object> item: getProps().entrySet()) {  
      if (item.getKey() instanceof String &&   
          item.getValue() instanceof String) {  
        result.put((String) item.getKey(), (String) item.getValue());  
      }  
    }  
    return result.entrySet().iterator();  
  }  
    
    
   
  public synchronized void setQuietMode(boolean quietmode) {  
    this.quietmode = quietmode;  
  }  
  
  /** For debugging.  List non-default properties to the terminal and exit. */  
  public static void main(String[] args) throws Exception {  
  }  
  
  
  public void readFields(DataInput in) throws IOException {  
    clear();  
    int size = WritableUtils.readVInt(in);  
    for(int i=0; i < size; ++i) {  
      set(org.apache.hadoop.io.Text.readString(in),   
          org.apache.hadoop.io.Text.readString(in));  
    }  
  }  
  
  public void write(DataOutput out) throws IOException {  
    Properties props = getProps();  
    WritableUtils.writeVInt(out, props.size());  
    for(Map.Entry<Object, Object> item: props.entrySet()) {  
      org.apache.hadoop.io.Text.writeString(out, (String) item.getKey());  
      org.apache.hadoop.io.Text.writeString(out, (String) item.getValue());  
    }  
  }  
}  

说明:Configuration实现了Iterable和Writable两个接口,其中实现Iterable是为了迭代,迭代出Configuration对象加载到内存中的所有name-value键值对。实现Writable是为了实现hadoop框架要求的序列化,可以将内存中的name-value序列化到硬盘,关于这两个接口的具体实现的话,我想不用再多说了,应该想的明白。
4.Configuration使用

合并资源指将多个配置文件合并,产生一个配置。如果有两个配置文件,也就是两个资源,如core-default.xml和core-site.xml,通过Configuration类的loadResources()方法,把它们合并成一个配置。代码如下:

Configuration conf = new Configuration();    
conf.addResource("core-default.xml");    
conf.addResource("core-site.xml");  

如果这两个配置资源都包含了相同的配置项,而且前一个资源的配置项没有标记为final,那么,后面的配置将覆盖前面的配置。

Hadoop配置系统还有一个很重要的功能,就是属性扩展。如配置项dfs.name.dir的值是 h a d o o p . t m p . d i r / d f s / n a m e , 其 中 , {hadoop.tmp.dir}/dfs/name,其中, hadoop.tmp.dir/dfs/name{hadoop.tmp.dir}会使用Configuration中的相应属性值进行扩展。

使用Configuration类的一般过程是:构造Configuration对象,并通过类的addResource()方法添加需要加载的资源;然后就可以使用get方法和set方法访问/设置配置项,资源会在第一次使用的时候自动加载到对象中。

http://f.dataguru.cn/thread-258563-1-1.html

http://www.cnblogs.com/shaoyexin/archive/2013/03/23/2977235.html

http://www.hackbase.com/tech/2014-12-12/70073.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值