1. 程式人生 > >記錄一個Hadoop Configuration易產生的誤用

記錄一個Hadoop Configuration易產生的誤用

原文連結:http://dongxicheng.org/mapreduce-nextgen/hadoop-configuration-usage/

Hadoop提供了一個擴充套件性極好的key/value格式的配置管理器Configuration,你可以設定任意的屬性名,並通過Configuration物件獲取對應的屬性值。

 

Hadoop Common中定義了Configuration的基本實現,其他模組/系統,比如MapReduce,HDFS,YARN,HBase等,均在這個基礎實現基礎上,實現了自己的Configuration,比如MapReduce中叫JobConf,HDFS中叫HdfsConfiguration,YARN中交YarnConfiguration,HBase中叫HBaseConfiguration,這些Configuration實現非常簡單,他們繼承基類Configuration,然後載入自己的xml配置檔案,通常這些配置檔案成對出現,比如MapReduce分別為mapred-default.xml和mapred-site.xml,HDFS分別為hdfs-default.xml,hdfs-site.xml。

Configuraion允許你通過兩種方式設定key/value格式的屬性,一種是通過set方法,另一種通過addResouce(String name),將一個xml檔案載入到Configuration中。本文重點談一下第二種使用過程中可能遇到的問題。大家請看下面一段程式碼:

1

2

3

4

Configuration conf = new Configuration();

conf.set(“xicheng.dong.age”, “200”)

conf. addResource(“Xicheng.xml”); //Xicheng.xml中設定了xicheng.dong.age為300

System.out.println(conf.get(“xicheng.dong.age”));// 此處會列印幾呢?

該程式最後會輸出200,而不是xicheng.xml中設定的300,為什麼呢?因為當一個配置屬性是使用者通過set方法設定的時,該屬性的來源將被標註為“programatically”,這樣的屬性是不能被addResource方法覆蓋的,必須通過set方法覆蓋或修改。在addResource實現中,首先會用指定的xml檔案覆蓋包含的所有屬性,之後再還原“programmatically”來源的那些屬性。

那麼問題來了,假設你的客戶端core-site.xml(建立Configuration物件時,該配置檔案會被預設載入)中配置了屬性xicheng.dong.age為300,而staging-hbase-site.xml中將其設成了400,那麼接下來一段程式碼會列印什麼結果呢?

1

2

3

Configuration conf = HBaseConfiguration.create(new Configuration());

conf. addResource(“staging-hbase-site.xml”);

System.out.println(conf.get(“xicheng.dong.age”));// 此處會列印幾呢?

最後結果將是300,而不是400。

如果你把第一句:

1

Configuration conf = HBaseConfiguration.create(new Configuration());

改為

1

Configuration conf = HBaseConfiguration.create();

結果就是你預想的400,為什麼呢?

這是由於HBaseConfiguration.create這個函式造成的,如果帶了Configuration引數,則實現如下:

1

2

3

4

5

6

7

8

9

10

11

public static Configuration create(final Configuration that) {

  Configuration conf = create();

  merge(conf, that);

  return conf;

}

 

public static void merge(Configuration destConf, Configuration srcConf) {

  for (Entry<String, String> e : srcConf) {

    destConf.set(e.getKey(), e.getValue());

  }

}

返回的Configuration中所有屬性均是通過set方法設定的,這些所有屬性均變成了” programatically”來源,之後便不可以被addResource覆蓋了。

如果不帶Configuration引數,HBaseConfiguration.create實現如下:

1

2

3

4

public static Configuration create() {

  Configuration conf = new Configuration();

  return addHbaseResources(conf);

}

所有屬性的來源均為某個xml檔案,比如”core-site.xml”,“hdfs-site.xml”等,這類屬性是可以被addResource覆蓋的。

總結

使用Hadoop Configuration進行程式設計的時候,當使用addResource載入xml中配置檔案時,一些屬性有可能不會被覆蓋掉(注意,final的屬性總是不可以覆蓋),此時一定要注意。你可以使用Configuration中的toString檢視各個xml檔案的載入順序,使用dumpConfiguration列印每個屬性的來源及isFinal屬性值