Hadoop配置文件解析


Hadoop源碼解析 2 --- Hadoop配置文件解析

1 Hadoop Configuration簡介
    Hadoop沒有使用java.util.Properties管理配置文件, 也沒有使用Apache Jakarta Commons Configuration管理配置文件,而是使用了一套獨有的配置文件管理系統,並提供自己的API,即使用 org.apache.hadoop.conf.Configuration處理配置信息。

    org.apache.hadoop.conf目錄結構如下:

  

2 Hadoop配置文件的格式解析
    Hadoop配置文件采用XML格式,下面是Hadoop配置文件的一個例子:

    <?xml version="1.0"?>
    <?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
    <configuration>
      <property>
         <name>io.sort.factor</name>
         <value>10</value>
         <description>The number of streams to merge at once while sorting  
         files.  This determines the number of open file handles.</description>
      </property>
    <property>
         <name>dfs.name.dir</name>
         <value>${hadoop.tmp.dir}/dfs/name</value>
         <description>Determines where on the local filesystem the DFS name  
         nodeshould store the name table(fsimage).  ……</description>
      </property>
    <property>
         <name>dfs.web.ugi</name>
         <value>webuser,webgroup</value>
         <final>true</final>
         <description>The user account used by the web interface.  
         Syntax: USERNAME,GROUP1,GROUP2, ……</description>
      </property>
    </configuration>

    Hadoop配置文件的根元素是configuration,一般只包含子元素property。每一個property元素就是一個配置 項,配置文件不支持分層或分級。每個配置項一般包括配置屬性的名稱name、值value和一個關於配置項的描述description;元素final 和Java中的關鍵字final類似,意味着這個配置項是“固定不變的”。final一般不出現,但在合並資源的時候,可以防止配置項的值被覆蓋。
    在 上面的示例文件中,配置項dfs.web.ugi的值是“webuser,webgroup”,它是一個final配置項;從description看, 這個配置項配置了Hadoop Web界面的用戶賬號,包括用戶名和用戶組信息。這些信息可以通過Configuration類提供的方法訪問。
    在 Configuration中,每個屬性都是String類型的,但是值類型可能是以下多種類型,包括Java中的基本類型,如 boolean(getBoolean)、int(getInt)、long(getLong)、float(getFloat),也可以是其他類型,如 String(get)、java.io.File(getFile)、String數組(getStrings)等。以上面的配置文件為 例,getInt("io.sort.factor")將返回整數10;而getStrings("dfs.web.ugi")返回一個字符串數組,該數 組有兩個元素,分別是webuser和webgroup。
    合並資源指將多個配置文件合並,產生一個配置。如果有兩個配置文件,也就是兩個資源,如core-default.xml和core-site.xml,通過Configuration類的loadResources()方法,把它們合並成一個配置。代碼如下:
    Configurationconf = new Configuration();  
    conf.addResource("core-default.xml");  
    conf.addResource("core-site.xml");
    如 果這兩個配置資源都包含了相同的配置項,而且前一個資源的配置項沒有標記為final,那么,后面的配置將覆蓋前面的配置。上面的例子中,core- site.xml中的配置將覆蓋core-default.xml中的同名配置。如果在第一個資源(core-default.xml)中某配置項被標記 為final,那么,在加載第二個資源的時候,會有警告提示。

3 直接運行Configuration.java則會調用默認配置文件部分結果如下:

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<configuration>
<property>
    <name>ipc.client.fallback-to-simple-auth-allowed</name>
    <value>false</value>
    <source>core-default.xml</source>
</property>
<property>
    <name>file.bytes-per-checksum</name>
    <value>512</value>
    <source>core-default.xml</source>
</property>
<property>
    <name>ipc.server.tcpnodelay</name>
    <value>false</value>
    <source>core-default.xml</source>
</property>
<property>
    <name>ftp.client-write-packet-size</name>
    <value>65536</value>
    <source>core-default.xml</source>
</property>
<property>
    <name>nfs3.mountd.port</name>
    <value>4272</value>
    <source>core-site.xml</source>
</property>
</configuration>

4 我們一般在wordcount程序中使用Configuration的set函數來添加或修改相關配置項,下面通過這種途徑解析其具體實現方式

4.1 Configuration conf = new Configuration(true)的具體實現如下(見4.1.2):

    Configuration有3個構造函數:

    4.1.1 如果在新建Configuration對象時無參數,則系統默認調用該構造函數

    public Configuration() {
        this(true);
    }

    4.1.2 如果在新建Configuration對象時有boolean類型形參,則調用該構造函數

    /**
     * 1 新建一個Configuration類,如果loadDefaults=false,
     * 則新建的Configuration實例默認不會加載默認的配置文件
     */
    public Configuration(boolean loadDefaults) {
        System.out.println("Configuration(boolean loadDefaults)");
        this.loadDefaults = loadDefaults;// 選擇是否加載默認配置文件,false為不加載,true加載
        System.out.println("loadDefaults: " + loadDefaults);
        updatingResource = new HashMap<String, String[]>();// 保存修改過的配置項
        synchronized (Configuration.class) {
            REGISTRY.put(this, null);
        }
    }

    4.1.3 如果在新建Configuration對象時有Configuration類型形參,則調用該構造函數

    /**
     * 
     * @param 調用其它Configuration對象的配置文件
     */
    @SuppressWarnings("unchecked")
    public Configuration(Configuration other) {
        this.resources = (ArrayList<Resource>) other.resources.clone();
        synchronized (other) {
            if (other.properties != null) {
                this.properties = (Properties) other.properties.clone();
            }
 
            if (other.overlay != null) {
                this.overlay = (Properties) other.overlay.clone();
            }
 
            this.updatingResource = new HashMap<String, String[]>(
                    other.updatingResource);
        }
 
        this.finalParameters = new HashSet<String>(other.finalParameters);
        synchronized (Configuration.class) {
            REGISTRY.put(this, null);
        }
        this.classLoader = other.classLoader;
        this.loadDefaults = other.loadDefaults;
        setQuietMode(other.getQuietMode());
    }

4.2 conf.set("fs.defaultFS", "file///");

    set函數有:

        public void set(String name, String value, String source)

        public void set(String name, String value)

        public synchronized void setIfUnset(String name, String value)

        public void setInt(String name, int value)

        public void setLong(String name, long value)

        public void setFloat(String name, float value)

        public void setDouble(String name, double value)

        public void setBoolean(String name, boolean value)

        public void setBooleanIfUnset(String name, boolean value)

        public <T extends Enum<T>> void setEnum(String name, T value)

        public void setTimeDuration(String name, long value, TimeUnit unit)

        public void setPattern(String name, Pattern pattern)

        public void setStrings(String name, String... values)

        public void setStrings(String name, String... values)

        public void setClass(String name, Class<?> theClass, Class<?> xface)

    其中,后面的set相關函數都是調用第一個set函數實現,下面就具體解析一下public void set(String name, String value, String source)

    /**
     * 
     * @Title        set
     * @Description  將參數name對應的value存入property中,如果該name在property中存在則覆蓋,否則添加
     * @param
     * @return
     * @throws
     */
    public void set(String name, String value, String source) {
        System.out.println("set(name, value, source) start !");
 
        Preconditions.checkArgument(name != null, "Property name must not be null");
        Preconditions.checkArgument(value != null, "The value of property " + name + " must not be null");
        DeprecationContext deprecations = deprecationContext.get();//保存不在配置文件的key
        System.out.println("deprecations: "+deprecations);
        System.out.println("deprecations.getDeprecatedKeyMap().isEmpty(): "+deprecations.getDeprecatedKeyMap().isEmpty());
        if (deprecations.getDeprecatedKeyMap().isEmpty()) {
            getProps();
        }
         
        getOverlay().setProperty(name, value);
        getProps().setProperty(name, value);
        String newSource = (source == null ? "programatically" : source);
 
        System.out.println("newSource: " + newSource);
        if (!isDeprecated(name)) {//檢測該name(key)項是否在配置文件中存在
             
            System.out.println("!isDeprecated(name): " + !isDeprecated(name));
             
            updatingResource.put(name, new String[] { newSource });//將該name(key)項參數添加進updatingResource中,說明該項已被修改
            String[] altNames = getAlternativeNames(name);//判斷該name(key)是否在默認配置文件中存在,如果存在則將name存入altNames中
             
            /**
             * 如果name(key)則默認配置文件中存在,則將name對應value存入updatingResource
             */
            if (altNames != null) {
                for (String n : altNames) {
                    System.out.println("altNames: "+n);
                    if (!n.equals(name)) {
                        getOverlay().setProperty(n, value);
                        getProps().setProperty(n, value);
                        updatingResource.put(n, new String[] { newSource });
                    }
                }
            }
        } else {
            String[] names = handleDeprecation(deprecationContext.get(), name);
            String altSource = "because " + name + " is deprecated";
            for (String n : names) {
                 
                System.out.println("names: "+names);
                 
                getOverlay().setProperty(n, value);
                getProps().setProperty(n, value);
                updatingResource.put(n, new String[] { altSource });
            }
        }
    }

5 Configuration測試程序如下:

/**  
 * @Title        ConfigurationTest.java
 * @Package      org.apache.hadoop.conftest
 * @Description  TODO
 * @date         2014年9月11日 上午11:27:14
 * @version      V1.0
 */
package org.apache.hadoop.conftest;
 
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
 
public class ConfigurationTest {
    public static void main(String args[]){
        Configuration conf = new Configuration(true);
        Path hadoop_mapred = new Path("hadoop-2.3.0/etc/hadoop/mapred-site.xml");
        Path hadoop_yarn = new Path("hadoop-2.3.0/etc/hadoop/yarn-site.xml");
        conf.addResource(hadoop_mapred);
        conf.addResource(hadoop_yarn);
        conf.set("mapreduce.jobtracker.system.dir", "file:///data1");//this conf can change the same parameter in the mapred-site.xml when the paramter is used
        conf.setInt("test1", 10);//This parameter will be add to property due to it not in the properties
        conf.set("fs.defaultFS", "file///data");//This parameter will change the same parameter value in the properties
        System.out.println(conf.get("test1"));
        System.out.println(conf.get("mapreduce.jobtracker.system.dir"));
        System.out.println(conf.get("yarn.resourcemanager.admin.address"));
        System.out.println("ok");
    }
}

 

  原創文章歡迎轉載,轉載時請注明出處。

  作者推薦文章:

    》Java自學之道

    總結5種比較高效常用的排序算法

    》如何獲取系統信息

    》如何生成二維碼過程詳解

    百度雲盤下載地址 http://pan.baidu.com/s/1eQzSiEA


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM