引言java
本文出於一個疑問:hadoop namenode -format到底在個人linux系統裏面作了些什麼?node
步驟linux
第1個文件bin/hadoopapache
Hadoop腳本位於hadoop根目錄下的bin目錄下,分佈式
打開以後閱讀源代碼:函數
在這裏$1即爲參數namenode工具
將COMMAND賦值爲$1,那麼COMMAND=namenodeoop
條件判斷語句的執行流到達#hdfs下的一行:網站
由於這一行判斷COMMAND是否等於namenode secondarynamenode等之一;spa
接着往下讀:
判斷"${HADOOP_HDFS_HOME}"/bin/hdfs存在,且爲一個文件,那麼就會執行
${HADOOP_HDFS_HOME}/bin/hdfs ${COMMAND/dfsgroups/groups} $@
在這裏${HADOOP_HDFS_HOME}/bin/hdfs 就是根目錄下的bin目錄下的hdfs腳本,${COMMAND/dfsgroups/groups}就是namenode,而$@則是-format;
第2個文件bin/hdfs
注意文件中間:
設置了2個變量CLASS 以及HADOOP_OTS
和文件末尾:
經過使用echo指令,能夠查看這些參數:
/usr/jdk1.8.0_51/bin/java
namenode
-Xmx1000m
-Djava.library.path=/usr/local/hadoop-2.6.0/lib -Djava.net.preferIPv4Stack=true -Dhadoop.log.dir=/usr/local/hadoop-2.6.0/logs -Dhadoop.log.file=hadoop.log -Dhadoop.home.dir=/usr/local/hadoop-2.6.0 -Dhadoop.id.str=hadoop -Dhadoop.root.logger=INFO,console -Dhadoop.policy.file=hadoop-policy.xml -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv4Stack=true -Dhadoop.log.dir=/usr/local/hadoop-2.6.0/logs -Dhadoop.log.file=hadoop.log -Dhadoop.home.dir=/usr/local/hadoop-2.6.0 -Dhadoop.id.str=hadoop -Dhadoop.root.logger=INFO,console -Dhadoop.policy.file=hadoop-policy.xml -Djava.net.preferIPv4Stack=true -Dhadoop.security.logger=INFO,RFAS -Dhdfs.audit.logger=INFO,NullAppender -Dhadoop.security.logger=INFO,RFAS -Dhdfs.audit.logger=INFO,NullAppender -Dhadoop.security.logger=INFO,NullAppender
org.apache.hadoop.hdfs.server.namenode.NameNode
-format
這是一個完整的java指令,
其中-D<名稱>=<值> 設置系統屬性,Xmx1000m設置JVM最大可用內存爲1GB;
這個不是重點,重點在後面:CLASS爲
org.apache.hadoop.hdfs.server.namenode.NameNode
也就是說java要經過一系列的選項和參數運行
org.apache.hadoop.hdfs.server.namenode.NameNode.class
接下來就是查看這個CLASS的源代碼了
第3個文件NameNode.java
這個文件位於
hadoop-2.6.0-src/hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/namenode/
其中hadoop-2.6.0-src是hadoop2.6.0的源碼,能夠直接在apache hadoop網站上下載,而後解壓就能夠了。
首先,找到main函數:
位於源碼第1497行,
沒錯,就是這樣一段短小精悍的代碼!
作了什麼呢?
第一部分,if條件語句暫時無視;
第二部分,try -catch模塊,
StringUtils.startupShutdownMessage(NameNode.class, argv, LOG);
根據名字分析,這個是用來顯示Message的.先無視.
重點在這一行代碼:
調用函數createNameNode(a,b);
找這個函數,在1365行:
返回類型爲NameNode的靜態成員函數.
依次作了這樣幾件事情:
1.寫LOG
2.建立一個HdfsConfiguration對象
3.建立一個StartupOption類的對象
4.設置StartupOption
5.switch-case
在這個條件語句模塊裏面找到FORMAT,
執行format函數,意思就是這個函數用來格式化namenode的了?
在903行,找到了:
跳到真正執行format指令的那一步
使用了2個對象fsn和fsImage,
留意在932行,
FSImage fsImage = new FSImage(conf, nameDirsToFormat, editDirsToFormat) ;
如今就須要弄明白FSImage是怎樣的一個類,以及format方法實現了怎樣的功能.
說明:如下步驟均在bluefish工具的協助下進行
第138行:
對應運行hadoop namenode -format時的log:
工做是由」storage.format(ns);」這行代碼完成的
打開NNStorage.java,找到format(ns)方法;
打開Storage.java,找到clearDirectory()方法:
接下來就是FileUtil.fullyDelete(curDir)了.
在源碼中沒有找到fs.FileUtil,在hadoop API中查找到了
public static void fullyDelete(FileSystem fs,Path dir);
這樣就刪除了一個目錄樹了,運行時,dir顯示爲:
/tmp/hadoop-hadoop/dfs/name
經檢查發現這個目錄依然存在,而且目錄下存在文件:
爲何會出現這種狀況?
並且,在hadoop2.6.0的源代碼中爲何找不到fs.FileUtil?
這些問題有待解決.
儘管如此,在format先後,對比文件佔用容量大小:
Namenode Format前:
NameNode Format後:
能夠看出,在執行了hadoop namenode -format以後,name目錄佔用的空間從1.1M 下降至24K
總結
本文的初衷是摸索出一條命令執行的流程,從而加深對hadoop系統的認識。
不過,這些步驟只是作了一點皮毛的功夫,並沒能觸及hadoop最核心的部分,無論是做爲一個分佈式系統也好,仍是一個java開源項目也好。
儘管如此,咱們能夠以此爲切入點,如同滾雪球同樣一點一點加深對這個生態系統的把握。