Hadoop源碼學習筆記(1)
——找到Main函數及讀一讀Configure類
前面在第一季中,我們簡單地研究了下Hadoop是什么,怎么用。在這開源的大牛作品的誘惑下,接下來我們要研究一下它是如何實現的。
提前申明,本人是一直搞.net的,對java略為生疏,所以在學習該作品時,會時不時插入對java的學習,到時也會擺一些上來,包括一下設計模式之類的。歡迎高手指正。
整個學習過程,我們主要通過eclipse來學習,之前已經講過如何在eclipse中搭建調試環境,這里就不多述了。
在之前源碼初窺中,我們已經找到了主要幾個的main函數入口。所以這里我們列一列計划:
-
FsShell main入口: org.apache.hadoop.fs.FsShell
-
NameNode main入口: org.apache.hadoop.hdfs.server.namenode.NameNode
-
DataNode main入口: org.apache.hadoop.hdfs.server.datanode.DataNode
-
JobTracker main入口: org.apache.hadoop.mapred.JobTracker
-
TaskTracker main入口: org.apache.hadoop.mapred.TaskTracker
我們會按這個順序來研究,至於其他的像SecondeNameNode之類的,在最后再來研究。
同樣,針對這些內容,我們還會分一下,第一步先來看DFS,第二步再來看MapReduce部份。
在研究DFS之前,我們看一下,這三者關系:
其中NameNode是客戶端的主接口,也是唯一的對接點,同時主要負責文件名目錄管理,以及數據DataNode的映射。
好了,要研究一塊,我們先來把程序跑起來吧。
在eclipse中我們很方便地就能找到每個模塊的對應的main函數,但還是有些不便,為了調試方便,我們再新建三個入口類:
自建入口類主要是為方便找到,然后這三個類中的代碼分別為:
FsShellEnter.java
-
import org.apache.hadoop.fs.FsShell;
-
-
public class FsShellEnter {
-
-
public static void main(String[] args) throws Exception {
-
FsShell.main(new String[]{"-ls"});
-
}
-
}
NamNodeEnter.java
-
public class NameNodeEnter {
-
-
public static void main(String[] args) throws Exception {
-
org.apache.hadoop.hdfs.server.namenode.NameNode.main(args);
-
}
-
}
DataNodeEnter.java
-
public class DataNodeEnter {
-
-
public static void main(String[] args) {
-
org.apache.hadoop.hdfs.server.datanode.DataNode.main(args);
-
}
-
}
運行之:
啟動命令行,運行:$ bin/hadoop namenode
然后在eclipse中,打開FsShellEnter.java,然后點擊運行,可以看到:
反過來,在eclipse中,打開NamNodeEnter.java,點擊運行,
在控制台中,可以輸入一堆的信息,說明正常了。
然后打開命令行,輸入:$ bin/hadoop fs -ls,可以看到:
這樣,說明正反運行都可以了。
當然這里我們沒有涉及文件內容操作,所以沒有DataNode也沒問題,不過可以自行試一下。
打開這幾個main函數,都可以看到上來都在初使化這個Configuration類。所以我們先來看一看這個類到底有點啥:
先看一下之前我們如何用這個類的:
-
Configuration conf = new Configuration();
-
String name = conf.get("fs.default.name");
-
System.out.println(name);
從字面意思及這段函數,可以看出Configuration類用於讀取配置文件的,且該程序就是讀出配置文件中fs.default.name的值。
觀察其構造函數:
-
public Configuration() {
-
this(true);
-
}
-
public Configuration(boolean loadDefaults) {
-
this.loadDefaults = loadDefaults;
-
if (LOG.isDebugEnabled()) {
-
LOG.debug(StringUtils.stringifyException(new IOException("config()")));
-
}
-
synchronized(Configuration.class) {
-
REGISTRY.put(this, null);
-
}
-
}
發現其本沒有做什么操作,主要設置了一個loadDefaults值為true。
然后再觀察get函數:
-
public String get(String name) {
-
return substituteVars(getProps().getProperty(name));
-
}
-
private synchronized Properties getProps() {
-
if (properties == null) {
-
properties = new Properties();
-
loadResources(properties, resources, quietmode);
-
if (overlay!= null)
-
properties.putAll(overlay);
-
}
-
return properties;
-
}
Get函數先是調用了substituteVars函數,這個是正則表達式處理函數,對返回值進行去非法字符處理,然后getProps函數中,對hashtable類型的properties進行判斷,如果為空則創建並進行初使化,否則直接返回。然后getProperty再根據其key值進行取值。
很明顯,這里是采用了懶加載的方式,就是說並沒有一開始加載配置文件中的數據,而是等要訪問時,才進行加載。
進一步看如何初使化的,loadResources函數:
-
private void loadResources(Properties properties,
-
ArrayList resources,
-
boolean quiet) {
-
if(loadDefaults) {
-
for (String resource : defaultResources) {
-
loadResource(properties, resource, quiet);
-
}
-
-
//support the hadoop-site.xml as a deprecated case
-
if(getResource("hadoop-site.xml")!=null) {
-
loadResource(properties, "hadoop-site.xml", quiet);
-
}
-
}
-
-
for (Object resource : resources) {
-
loadResource(properties, resource, quiet);
-
}
-
}
這里第5行可看到先加載了defaultResources中的資源,然后再加載hadoop-site.xml(第10行)。
defaultResources有哪些呢,一步步找,可以看到:
-
static{
-
...
-
addDefaultResource("core-default.xml");
-
addDefaultResource("core-site.xml");
-
}
-
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工作起來。