一、NameNode 的介面分析
1. NameNode本質
經過前面的學習,可以知道NameNode 本身就是一個java 程式。觀察RPC.getServer()方法的第一個引數,發現是this,說明NameNode 本身就是一個位於服務端的被呼叫物件,即NameNode 中的方法是可以被客戶端程式碼呼叫的。根據RPC 執行原理可知,NameNode暴露給客戶端的方法是位於介面中的。
我們檢視NameNode 的原始碼,如圖1.1所示。
圖 1.1
可以看到NameNode 實現了ClientProtocal、DatanodeProtocal、NamenodeProtocal 等介面。
2. NameNode的介面
2.1 DFSClient 呼叫ClientProtocal
<1> 這個介面是供客戶端呼叫的。這裡的客戶端不是指的我們自己寫的程式碼,而是hadoop 的一個類叫做DFSClient。在DFSClient 中會呼叫ClientProtocal 中的方法,完成一些操作。
<2>該介面中的方法大部分是對HDFS 的操作,如create、delete、mkdirs、rename 等。
2.2 DataNode 呼叫DatanodeProtocal
這個介面是供DataNode 呼叫的。DataNode 呼叫該介面中的方法向NameNode 報告本節點的狀態和block 資訊。NameNode 不能向DataNode 傳送訊息, 只能通過該介面中方法的返回值向DataNode 傳遞訊息。
2.3 SecondaryNameNode 呼叫NamenodeProtocal
這個介面是供SecondaryNameNode 呼叫的。SecondaryNameNode 是專門做NameNode 中edits 檔案向fsimage 合併資料的。
二、DataNode 的介面分析
按照分析NameNode 的思路,看一下DataNode 的原始碼介面,如圖2.1 所示。
這裡有兩個介面,分別是InterDatanodeProtocal、ClientDatanodeProtocal。這裡就不展開分析了。讀者可以根據上面的思路獨立分析。
三、HDFS的資料處理過程分析
1. HDFS 的寫資料過程分析
1.1 通過FileSystem 類可以操控HDFS
那我們就從這裡開始分析寫資料到HDFS 的過程。在我們向HDFS 寫檔案的時候,呼叫的是FileSystem.create(Path path)方法,我們檢視這個方法的原始碼,通過跟蹤內部的過載方法,可以找到如圖3.1所示的呼叫。
這個方法是抽象類,沒有實現。那麼我們只能向他的子類尋找實現。
1.2 檢視DistributedFileSystem類的原始碼
FileSystem 有個子類是DistributedFileSystem,在我們的偽分佈環境下使用的就是這個類。我們可以看到DistributedFileSystem 的這個方法的實現,如圖3.2示。
圖3.2
在圖3.2中,注意第186 行的返回值FSDataOutputStream。這個返回值物件呼叫了自己的構造方法,構造方法的第一個引數是dfs.create()方法。
1.3 關注一下這裡的dfs 物件是誰,create 方法做了什麼事情。
現在進入這個方法的實現,如圖3.3 所示。
在圖3.3 中,返回值正是第866行建立的物件。
1.4 檢視這個類的原始碼
如圖3.4 所示。
圖3.4
在圖3.4 中, 可以看到, 這個類是DFSClient 的內部類。在類內部通過呼叫namenode.create()方法建立了一個輸出流。
1.5 我們再看一下namenode 物件是什麼型別
如圖3.5所示。
圖3.5
在圖3.5 中,可以看到namenode 其實是ClientProtocal 介面。
1.6 那麼,這個物件是什麼時候建立的那?
檢視該物件,如圖3.6 所示。
可以看出,namenode 物件是在DFSClient 的建構函式呼叫時建立的,即當DFSClient 物件存在的時候,namenode 物件已經存在了。
1.7 整個呼叫過程
至此,我們可以看到,使用FileSystem 物件的api 操縱HDFS,其實是通過DFSClient 物件訪問NameNode 中的方法操縱HDFS 的。這裡的DFSClient 是RPC 機制的客戶端,NameNode是RPC 機制的服務端的呼叫物件,整個呼叫過程如圖3.7所示。
在整個過程中,DFSClient 是個很重要的類,從名稱就可以看出,他表示HDFS 的Client,是整個HDFS 的RPC 機制的客戶端部分。我們對HDFS 的操作,是通過FileSsytem 呼叫的DFSClient 裡面的方法。FileSystem 是封裝了對DFSClient 的操作,提供給使用者使用的。
2. HDFS 的讀資料過程分析
2.1 對FileSystem 類分析
我們繼續對FileSystem 類分析,讀資料使用的是open(…)方法,我們可以看到原始碼,如圖3.8 所示。
圖3.8
在圖3.8 中,返回的是DFSClient 類中DFSDataInputStream 類.顯而易見,這是一個內部類。
2.2 檢視這個內部類的構造方法的原始碼
這個內部類的建構函式,有兩個形參,第一個引數是dfs.open(…)建立的物件。我們看一下方法的原始碼,如圖3.9所示。
在圖3.9的實現中,返回的是一個DFSInputStream 物件。
2.3 檢視DFSInputStream這個類的構造方法原始碼
該物件中含有NameNode 中的資料塊資訊。我們看一下這個類的構造方法原始碼,如圖3.10 所示。
圖3.10
2.4 檢視獲取資料塊的資訊方法原始碼
在圖3.10中,這個構造方法中最重要的語句是第1836 行,開啟資訊,從第1842 行開始是openInfo()的原始碼,截圖顯示不全。注意第1841 行,是獲取資料塊的資訊的。我們檢視這一行的原始碼,如圖3.11所示。
圖3.11
從圖3.11 中可以看到,獲取資料塊資訊的方法也是通過呼叫namenode 取得的。這裡的namenode 屬性還是位於DFSClient 中的。通過前面的分析,我們已經知道,在DFSClient類中的namenode 屬性是ClientProtocal。