Hadoop學習筆記(9) java
——源碼初窺 node
以前咱們把Hadoop算是入了門,下載的源碼,寫了HelloWorld,簡要分析了其編程要點,而後也編了個較複雜的示例。接下來其實就有兩條路可走了,一條是繼續深刻研究其編程及部署等,讓其功能使用的淋漓盡致。二是停下來,先看看其源碼,研究下如何實現的。在這裏我就選擇第二條路。 linux
研究源碼,那咱們就來先看一下整個目錄裏有點啥: c++
這個是剛下完代碼後,目錄列表中的內容。 web
目錄/文件apache |
說明編程 |
binwindows |
下面存放着可執行的sh命名,全部操做都在這裏app |
confeclipse |
配置文件所在目錄 |
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++ |
linux下amd64-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 |
至此整個目錄有了一個初步的瞭解,接下來,那就能夠順着這些入口深刻研究了。且慢,還差個調試環境呢! 下一章來。