Hadoop學習筆記(9) ——源碼初窺


Hadoop學習筆記(9)

——源碼初窺

之前我們把Hadoop算是入了門,下載的源碼,寫了HelloWorld,簡要分析了其編程要點,然后也編了個較復雜的示例。接下來其實就有兩條路可走了,一條是繼續深入研究其編程及部署等,讓其功能使用的淋漓盡致。二是停下來,先看看其源碼,研究下如何實現的。在這里我就選擇第二條路。

研究源碼,那我們就來先看一下整個目錄里有點啥:

這個是剛下完代碼后,目錄列表中的內容。

目錄/文件

說明

bin

下面存放着可執行的sh命名,所有操作都在這里

conf

配置文件所在目錄

ivy

Apache Ivy是專門用來管理項目的jar包依賴的,這個是ivy的主要目錄

lib

引用的庫文件目錄,里面存放用到的jar包

src

這個里面就是主要的源碼了

build.xml

用於編譯的配置文件。 編譯我們用的是ant

CHANGES.txt

文本文件,記錄着本版本的變更歷史

ivy.xml

Ivy的配置文件

LICENSE.txt

文件本文件,

NOTICE.txt

文本文件,記錄着需要注意的地方

README.txt

說明文件。

 

進入src目錄,我們看到了:

目錄/文件

說明

ant

為ant命令編寫的擴展指定

benchmarks

筆者也沒弄明白L

build

就存放一個打包信息文件

c++

linuxamd64-64位系統以及i386-32位系統提供的庫文件集合

contrib

是開源界或第三方為hadoop編寫的一些擴展程序,如eclipse插件等

core

Hadoop的核心代碼

docs

文檔

examples

示例程序

hdfs

HDFS模塊的代碼

marped

MapReduce模塊代碼

native

筆者也沒弄明白L

test

測試程序

tools

工具集

webapps

網頁管理工具的代碼,主要是jsp文件。

fixFontsPath.sh

用於修正字體路徑的批處理命令。

saveVersion.sh

用於生成打包信息文件批處理命令。

 

這些目錄及文件命名及分布還是很清晰的,基本上根據命名也能猜出其意思來了。當我們拿到這些文件時,做了兩件事,編譯運行,接下來我們一塊塊仔細來看看。

 

編譯

當我們拿到手時,第一章中講到,我們用了以下命令就完成了編譯:

~/hadoop-0.20.2$ant

~/hadoop-0.20.2$ant jar

~/hadoop-0.20.2$ant examples

在編譯完后,我們發現,目錄中多了一個build文件夾。這個文件夾下,我們發現有大量的子文件夾,再深入看,可以找到了N多個.class文件。那這個正是java程序的編譯產出物。

我們在第5章中,簡要的描述了java程序與.net的差別。一個.java程序對應一個.class文件,手動的話用javac來編譯。我們要將這么多的java文件都要編譯成一個個的.class文件,敲javac命令肯定是不行的,我們得找個打包處理的辦法。這個就是ant。簡單的說ant就是將編譯命名進行打包處理的程序,這個程序有一個配置文件就是build.xml。所以我們進入hadoop根目錄后輸入了ant后就開始運行了,因為它在當前目錄下找到了build.xml文件。那ant能做啥,其實百度上一搜就有很多了。這里就不詳述了。我們簡要的來看一下build.xml。 打開一看,build.xml文件貌似很復雜,有1千8百多行。不要怕,簡單看下:

一上來,定義了一個project,看來這是一個工程,有名稱和default屬性(default后面看是啥)。

接下來發現是一堆的property,然后是name-value的健值。應該猜的出,這些就是后面真正執行用的一些變量或參數。

再往下,看到有這些:

看到有target,然后取了個名,字面意思是目標,然后看看子結點,發現是mkdir,好熟悉的字眼,這不是在創建目錄么,看下第一個dir是啥,${build.dir}。然后立即跑回上面property中,看下是否有呢?

果然,這個就是在編譯后的產生的目錄,第一步創建之,很正常。

既然這樣,這個target就是一個個目標,然后往下拖一下,發現下面的都是一個個的目錄,全文搜索一下:

發現里面有106個。

繼續搜,發現了亮點:

這個target(目標)好眼熟,~/hadoop-0.20.2$ant jar 沒錯,當時在編譯時,輸入這個命令后,就產出了一個jar文件。看來這個target就是在形成jar文件,略看下其子命令,的確就是在生成jar包了。

簡單了解了這個target后,就可以繼續找找,我們的examples命令了。現回想起來,在編譯時第一個命令是~/hadoop-0.20.2$ant,而這個好象沒有寫target么?又想到了:

難道這個default就是傳說中的默認目標? compile。 熬不住了,立即展開搜索:

果然,猜的沒錯。找到了這個默認目錄,然后發現好多target后還有depends,字面意思,依賴吧,然后可以繼續找,依賴里面的目錄,也是一個個的target。

了解了這個之后,我們又在想,現在知道的target也就 默認、jar、example,還有哪些呢,我們就可以搜target name="這個字符。當然會發現有很多,但是不是每個都對我們有用,因為好多是為了編寫方便,將一個大的拆成多個小的,以便於維護。至於哪些有用的,這里我就不一一列出。可以自己看看。 比如clean就不錯,可以把編譯后的結果清理掉,還原到開始狀態。

 

編譯成.class包括jar包現在都沒問題了。我們知道hadoop是用java寫的,在src下可找到大量java類文件。難道這個hadoop就沒有引用一個第三方的組件?答案是有的,一開始沒看到幾個,在lib下就只有幾個。 但是在ant完后,在build下搜,發現有好多個jar文件。 哪來的? 下載的。誰負責下載的,為什么知道要下載這些文件?

我們發現,在build.xml中,第一個target init就有depends:

然后就可以一級級查到,是通用ivy進行下載的,至於下載哪些,在ivy.xml中就有配置。好了,這塊並不是我們的重點,了解到這里就夠了,反正所用到的lib文件都下來了。

 

運行

在第一章中,我們了解到啟用整個hadoop,全到了這個命令:bin/start-all.sh,關閉是用到了bin/stop-all.sh。而這個又是什么文件,我們來研究一下看。

不急看start-all, 我們打開bin目錄看一下:

在bin下有很多個sh文件,hadoop這個命令,雖然沒有后綴,但打開看后,發現跟其他sh文件樣,類似的腳本。

什么是sh文件? 在windows中我們知道bat文件,就是將若干個命令放到一個文件中,依次執行,稱之為批處理文件。在Linux中,這個bat文件就是sh文件了。

先不急着打開文件內容,我們觀察下所以文件,看到下面8個,很有規律,4個startXXX.sh然后4個stopXXX.sh文件。看來這些就是用戶啟動和關閉hadoop用的。

打開start-all.sh,發現內容並不多,也很好理解:

 

這里,先調了一下hadoop-config.sh,字面意思,設置配置文件。然后再調了start-dfs 和start-mapred。這里就很明顯了,start-all是啟動整個hadoop,然后里面包含了兩個動作,啟動dfs和mapreduce。 同理,如果我想只啟動dfs,那么只需要運行start-dfs.sh即可。

同樣,打開stop-all.sh文件,也可以看到比較簡單,

發現是分別調了stop-mapred.sh和stop-dfs.sh這兩個文件。

這里我們就不每個文件進行分析了,我們只挑幾個關鍵文件看一下。

 

繼續前行,打開start-dfs.sh和stop-dfs.sh文件,發現里面

 

大家可以打開其他所有的startXX和stopXX文件,發現所有的操作都又轉入了hadoop-daemon.sh和hadoop-daemons.sh這兩個命令,同時傳入了參數—config stop/start 名稱 (opt參數)。

繼續,打開hadoop-daemons.sh,發現內容也很簡單:

這里,先調用了slaves.sh后,又調回來hadoop-daemon.sh,所以現在目標焦點就只有兩個了hadoop-daemon.sh和slaves.sh了。打開slaves.sh看一下:

這個文件的字面意思應該就是啟動各分布式子機的hadoop咯。看一下代碼,第一個if與fi之間,可以看到是取得conf文件夾下的slaves文件。記得在配置分配布式里面,在slaves中配置寫了是node1 node2用回車換行隔開。 所以第二段代碼,for循環slaves中的文件,然后調用ssh命令,調到了子系統中的相應的命令,這里,就完全可以想通了,為什么子系統中部署的hadoop目錄需要與主目錄相同,然后slaves中配置的是子系統機器的名稱。

到這里,整個bin目錄的腳本,就集中在剩下的兩個hadoop-daemon.sh和hadoop了。勝利在望了。先看hadoop-daemon.sh。

一開始,代碼是在取參數,startstop和command,從前面的傳入可以看到,startstop參數傳的是start和stop,看來是啟動和關閉, command是namenode、datanode之類的。

繼續往下看:

case語句下進行了分類,將start和stop命令分開處理。在start時,先是創建一個文件夾PID_DIR,具體值可以看上面,然后第一段if,是在判斷進程有沒有啟動,然后最關健是執行nohup nice …. /bin/hadoop。也就是說歸根到底又都是在執行hadoop命令了。這里nohup,是指啟動進程后不被卡住,即轉為后台進程,又稱守護進程,所以該sh文件命名為daemon也不為過。

然后stop段時,把進程進行kill掉。這里有疑問了,啟動的命令kill里需要知道進程的PID,而kill里哪里獲取呢,在啟動時,將啟動進程后的pid記錄在PID文件夾內,然后kill時就可以跟據這些PID來處理了。這塊在代碼中,也比較清晰的體現了。

 

在執行hadoop命令時,又將namenode、datanode、secondarynamenode等命令傳入。所以現在可以打開hadoop命令文件了:(這里直接跳入重點看)

這里,看到有大量的if語句,條件是command判斷,然后執行中對class和hadoop_opts進行了賦值。 繼續往下看:(在最后)

我們發現,是在執行java命令,傳入的main函數入口正是上面條件處理中的CLASS變量。換句話說,這個CLASS應該對應一個個的main函數咯? 驗證一下,找一個,比如dataNode,其CLASS是org.apache.hadoop.hdfs.server.datanode.DataNode。按這路徑在src中找到文件DataNode.java,打開,然后搜main:

果然,完全應正了我們的想法。

總結一下:整個hadoop程序,是一個java為主的程序,在編譯是將.class文件生成在build目錄,在運行時,雖然執行的是.sh文件,但一步步,最終都是在執行java命令,傳入的入口,就是各個子程序的main函數入口。

 

想法1:看了這個sh命令后,又有一個想法,之前通過starg-all.sh就把整個程序啟動起來了,而且是在后台運行的,輸出內容只能從log文件夾內看,能否直接從命令行啟動呢? 當然行,輸入 bin/hadoop namenode試試,果然,啟動了namenode程序,然后日志信息也直接打印在屏幕上了。

想法2:既然從hadoop這個sh文件夾內,可以看到所有的入口,那就可以整理一下,所有的入口成一個列表,方便以后找到其main函數。

命令

入口

namenode

org.apache.hadoop.hdfs.server.namenode.NameNode

secondarynamenode

org.apache.hadoop.hdfs.server.namenode.SecondaryNameNode

datanode

org.apache.hadoop.hdfs.server.datanode.DataNode

fs / dfs

org.apache.hadoop.fs.FsShell

dfsadmin

org.apache.hadoop.hdfs.tools.DFSAdmin

mradmin

org.apache.hadoop.mapred.tools.MRAdmin

fsck

org.apache.hadoop.hdfs.tools.DFSck

balancer

org.apache.hadoop.hdfs.server.balancer.Balancer

jobtracker

org.apache.hadoop.mapred.JobTracker

tasktracker

org.apache.hadoop.mapred.TaskTracker

job

org.apache.hadoop.mapred.JobClient

queue

org.apache.hadoop.mapred.JobQueueClient

pipes

org.apache.hadoop.mapred.pipes.Submitter

version

org.apache.hadoop.util.VersionInfo

jar

org.apache.hadoop.util.RunJar

distcp

org.apache.hadoop.tools.DistCp

daemonlog

org.apache.hadoop.log.LogLevel

archive

org.apache.hadoop.tools.HadoopArchives

sampler

org.apache.hadoop.mapred.lib.InputSampler

 

至此整個目錄有了一個初步的了解,接下來,那就可以順着這些入口深入研究了。且慢,還差個調試環境呢! 下一章來。


免責聲明!

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



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