Hadoop源碼學習筆記(1) ——第二季開始——找到Main函數及讀一讀Configure類


Hadoop源碼學習筆記(1)

——找到Main函數及讀一讀Configure類

前面在第一季中,我們簡單地研究了下Hadoop是什么,怎么用。在這開源的大牛作品的誘惑下,接下來我們要研究一下它是如何實現的。

提前申明,本人是一直搞.net的,對java略為生疏,所以在學習該作品時,會時不時插入對java的學習,到時也會擺一些上來,包括一下設計模式之類的。歡迎高手指正。

整個學習過程,我們主要通過eclipse來學習,之前已經講過如何在eclipse中搭建調試環境,這里就不多述了。

在之前源碼初窺中,我們已經找到了主要幾個的main函數入口。所以這里我們列一列計划:

  1. FsShell main入口: org.apache.hadoop.fs.FsShell
  2. NameNode main入口: org.apache.hadoop.hdfs.server.namenode.NameNode
  3. DataNode main入口: org.apache.hadoop.hdfs.server.datanode.DataNode
  4. JobTracker main入口: org.apache.hadoop.mapred.JobTracker
  5. TaskTracker main入口: org.apache.hadoop.mapred.TaskTracker

我們會按這個順序來研究,至於其他的像SecondeNameNode之類的,在最后再來研究。

同樣,針對這些內容,我們還會分一下,第一步先來看DFS,第二步再來看MapReduce部份。

在研究DFS之前,我們看一下,這三者關系:

其中NameNode是客戶端的主接口,也是唯一的對接點,同時主要負責文件名目錄管理,以及數據DataNode的映射。

 

好了,要研究一塊,我們先來把程序跑起來吧。

在eclipse中我們很方便地就能找到每個模塊的對應的main函數,但還是有些不便,為了調試方便,我們再新建三個入口類:

自建入口類主要是為方便找到,然后這三個類中的代碼分別為:

FsShellEnter.java

  1. import org.apache.hadoop.fs.FsShell;
  2.  
  3. public class FsShellEnter {
  4.  
  5.    public static void main(String[] args) throws Exception {
  6.       FsShell.main(new String[]{"-ls"});
  7.    }
  8. }

NamNodeEnter.java

  1. public class NameNodeEnter {
  2.  
  3.    public static void main(String[] args) throws Exception {
  4.       org.apache.hadoop.hdfs.server.namenode.NameNode.main(args);
  5.    }
  6. }

DataNodeEnter.java

  1. public class DataNodeEnter {
  2.  
  3.    public static void main(String[] args) {
  4.       org.apache.hadoop.hdfs.server.datanode.DataNode.main(args);
  5.    }
  6. }

運行之:

啟動命令行,運行:$ bin/hadoop namenode

然后在eclipse中,打開FsShellEnter.java,然后點擊運行,可以看到:

 

反過來,在eclipse中,打開NamNodeEnter.java,點擊運行,

在控制台中,可以輸入一堆的信息,說明正常了。

然后打開命令行,輸入:$ bin/hadoop fs -ls,可以看到:

這樣,說明正反運行都可以了。

當然這里我們沒有涉及文件內容操作,所以沒有DataNode也沒問題,不過可以自行試一下。

 

打開這幾個main函數,都可以看到上來都在初使化這個Configuration類。所以我們先來看一看這個類到底有點啥:

先看一下之前我們如何用這個類的:

  1. Configuration conf = new Configuration();
  2. String name = conf.get("fs.default.name");
  3. System.out.println(name);

從字面意思及這段函數,可以看出Configuration類用於讀取配置文件的,且該程序就是讀出配置文件中fs.default.name的值。

觀察其構造函數:

  1. public Configuration() {
  2.     this(true);
  3. }
  4.  public Configuration(boolean loadDefaults) {
  5.     this.loadDefaults = loadDefaults;
  6.     if (LOG.isDebugEnabled()) {
  7.       LOG.debug(StringUtils.stringifyException(new IOException("config()")));
  8.     }
  9.     synchronized(Configuration.class) {
  10.       REGISTRY.put(this, null);
  11.     }
  12.   }

發現其本沒有做什么操作,主要設置了一個loadDefaults值為true。

然后再觀察get函數:

  1.   public String get(String name) {
  2.     return substituteVars(getProps().getProperty(name));
  3.   }
  4. private synchronized Properties getProps() {
  5.     if (properties == null) {
  6.       properties = new Properties();
  7.       loadResources(properties, resources, quietmode);
  8.       if (overlay!= null)
  9.         properties.putAll(overlay);
  10.     }
  11.     return properties;
  12.   }

Get函數先是調用了substituteVars函數,這個是正則表達式處理函數,對返回值進行去非法字符處理,然后getProps函數中,對hashtable類型的properties進行判斷,如果為空則創建並進行初使化,否則直接返回。然后getProperty再根據其key值進行取值。

很明顯,這里是采用了懶加載的方式,就是說並沒有一開始加載配置文件中的數據,而是等要訪問時,才進行加載。

進一步看如何初使化的,loadResources函數:

  1. private void loadResources(Properties properties,
  2.                              ArrayList resources,
  3.                              boolean quiet) {
  4.     if(loadDefaults) {
  5.       for (String resource : defaultResources) {
  6.         loadResource(properties, resource, quiet);
  7.       }
  8.  
  9.       //support the hadoop-site.xml as a deprecated case
  10.       if(getResource("hadoop-site.xml")!=null) {
  11.         loadResource(properties, "hadoop-site.xml", quiet);
  12.       }
  13.     }
  14.  
  15.     for (Object resource : resources) {
  16.       loadResource(properties, resource, quiet);
  17.     }
  18.   }

這里第5行可看到先加載了defaultResources中的資源,然后再加載hadoop-site.xml(第10行)。

defaultResources有哪些呢,一步步找,可以看到:

  1. static{
  2.    ...
  3.     addDefaultResource("core-default.xml");
  4.     addDefaultResource("core-site.xml");
  5.   }
  6.  public static synchronized void addDefaultResource(String name) {...}

從這里看到,默認加載了core-default.xml和core-site.xml這兩個文件。

到這里,我們可以再打開這3個XML來看看了:

 

從這兩個文件,我們可以看出,配置文件中存儲就是用的key-value的健值對方式,然后加一個description對該配置項的描述。所以程序中讀取也是傳入key即可獲取value。

同時,core-site.xml是我們自己配置文件,仔細看,可發現,在core-defalut.xml中也有一些相同的配置項。加載時先加載defalut再site,后者有相同key時覆蓋前者。

所以換句話說,我們可以不配置hadoop.tmp.dir 則默認就在上面default中的/tmp….目錄。

同時也可相到,hadoop的其他配置,就可以參考core-default.xml中的了。 可以直接改,也可以在core-site中再復制一份再改。

 

繼續觀察Configuration還有哪些方法:

發現其中有很多個get函數,然后是返回各種不同類型的。這樣就方便我們取值后直接處理了。

同時,可以看到還有一堆的set函數。這些set函數追進去看,是在修改hashtable的,並沒有保存。所以說這些用途也是可見的,不用配置文件也可以讓Configuration工作起來。

 


免責聲明!

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



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