HDFS 的 RPC 機制


4.6. HDFS 的 RPC 機制
RPC 是遠程過程調用 (Remote Procedure Call),即遠程調用其他虛擬機中運行的 java
object。 RPC 是一種客戶端/服務器模式, 那么在使用時包括服務端代碼和客戶端代碼, 還有
我們調用的遠程過程對象。


HDFS 的運行就是建立在此基礎之上的。本章通過分析實現一個簡單的 RPC 程序來分析
HDFS 的運行機理。本節難度偏大,讀者可以在第二、三遍閱讀本書時掌握即可。
下面的代碼是服務端代碼 。

核心在於第 5 行的 RPC.getServer 方法, 該方法有四個參數, 第一個參數是被調用的 java
對象, 第二個參數是服務器的地址, 第三個參數是服務器的端口。 獲得服務器對象后, 啟動
服務器。這樣,服務器就在指定端口監聽客戶端的請求。
下面的代碼是被調用的遠程對象類。

被調用的遠程對象實現了接口 MyBizable,這里面有兩個方法被實現,一個就是 hello
方法, 另一個是 getProtocalVersion 方法。這個 hello 方法內部有個輸出語句。
下面的代碼是遠程調用類的接口定義。

 

這個接口中的方法就是剛才的 Biz 中實現的方法。接口繼承的 VersionedProtocal, 是
hadoop 的 RPC 的接口,所有的 RPC 通信必須實現這個一接口,用於保證客戶端和服務端的
端口一致。服務端被調用的類必須繼承這個接口 VersionedProtocal。
下面是客戶端代碼,這里使用的調用對象的接口。

以上代碼中核心在於 RPC.getProxy(),該方法有四個參數,第一個參數是被調用的接口
類, 第二個是客戶端版本號, 第三個是服務端地址。 返回的代理對象, 就是服務端對象的代
理,內部就是使用 java.lang.Proxy 實現的。
運行時,先啟動服務端,再啟動客戶端。讀者可以服務端和客戶端輸出信息。
從上面的 RPC 調用中,可以看出: 在客戶端調用的業務類的方法是定義在業務類的接
口中的。該接口實現了 VersionedProtocal 接口。
現在我們在命令行執行 jps 命令,查看輸出信息,如圖 5-1 所示。

可以看到一個 java 進程,是“MyServer”,該進程正是我們剛剛運行的 rpc 的服務端類
MyServer。大家可以聯想到我們搭建 hadoop 環境時,也執行過該命令用來判斷 hadoop 的
進程是否全部啟動,如圖 3-。那么可以判斷, hadoop 啟動時產生的 5 個 java 進程也應該是
RPC 的服務端。 我們觀察 NameNode 的源代碼, 如圖 5-2, 可以看到 NameNode 確實創建了
RPC 的服務端。

4.7. NameNode 的接口分析
由 5.1 節分析, 可以看到 NameNode 本身就是一個 java 進程。觀察圖 5-2 中 RPC.getServer()
方法的第一個參數,發現是 this,說明 NameNode 本身就是一個位於服務端的被調用對象,
即 NameNode 中的方法是可以被客戶端代碼調用的。根據 RPC 運行原理可知, NameNode
暴露給客戶端的方法是位於接口中的。
我們查看 NameNode 的源碼,如圖 5-3 所示。

可以看到 NameNode 實現了 ClientProtocalDatanodeProtocalNamenodeProtocal 等接
口。下面我們逐一分析這些接口。
DFSClient 調用 ClientProtocal
這個接口是供客戶端調用的。這里的客戶端不是指的我們自己寫的代碼,而是
hadoop 的一個類叫做 DFSClient。在 DFSClient 中會調用 ClientProtocal 中的方法, 完
成一些操作。
該接口中的方法大部分是對 HDFS 的操作, 如 createdeletemkdirsrename 等。
DataNode 調用 DatanodeProtocal
這個接口是供 DataNode 調用的。 DataNode 調用該接口中的方法向 NameNode 報告
本節點的狀態和 block 信息。
NameNode 不能向 DataNode 發送消息,只能通過該接口中方法的返回值向
DataNode 傳遞消息。
SecondaryNameNode 調用 NamenodeProtocal
這個接口是供 SecondaryNameNode 調用的。 SecondaryNameNode 是專門 做
NameNode edits 文件向 fsimage 合並數據的。
4.8. DataNode 的接口分析
按照分析 NameNode 的思路,看一下 DataNode 的源碼接口,如圖 5-4 所示。

這里有兩個接口,分別是 InterDatanodeProtocal、 ClientDatanodeProtocal。這里就不展
開分析了。讀者可以根據上面的思路獨立分析。
4.9. HDFS 的寫數據過程分析
我們通過 FileSystem 類可以操控 HDFS, 那我們就從這里開始分析寫數據到 HDFS 的過程。
在我們向 HDFS 寫文件的時候,調用的是 FileSystem.create(Path path)方法,我們查看這
個方法的源碼,通過跟蹤內部的重載方法,可以找到如圖 5-5 所示的調用。

這個方法是抽象類, 沒有實現。 那么我們只能向他的子類尋找實現。 FileSystem 有個子
類是 DistributedFileSystem ,在我們的偽分布環境下使用的就是這個類。我們可以看到
DistributedFileSystem 的這個方法的實現,如圖 5-6 所示。

在圖 5-6 中, 注意第 185 行的返回值 FSDataOutputStream。 這個返回值對象調用了自己
的構造方法, 構造方法的第一個參數是 dfs.create()方法。 我們關注一下這里的 dfs 對象是誰,
create 方法做了什么事情。現在進入這個方法的實現,如圖 5-7 所示。

 

在圖 5-7 中, 返回值正是第 713 行創建的對象。 這個類有什么神奇的地方嗎?我們看一
下他的源碼,如圖 5-8 所示。

在 圖 5-8 中 , 可 以 看 到 , 這 個 類 是 DFSClient 的 內 部 類 。 在 類 內 部 通 過 調 用
namenode.create()方法創建了一個輸出流。 我們再看一下 namenode 對象是什么類型, 如圖
5-9 所示。

在圖 5-9 中, 可以看到 namenode 其實是 ClientProtocal 接口。 那么, 這個對象是什么時
候創建的那?如圖 5-10 所示。

可以, namenode 對象是在 DFSClient 的構造函數調用時創建的,即當 DFSClient 對象存
在的時候, namenode 對象已經存在了。
至此,我們可以看到,使用 FileSystem 對象的 api 操縱 HDFS,其實是通過 DFSClient 對
象訪問 NameNode 中的方法操縱 HDFS 的。這里的 DFSClient 是 RPC 機制的客戶端, NameNode
是 RPC 機制的服務端的調用對象,整個調用過程如圖 5-11 所示。

在整個過程中, DFSClient 是個很重要的類, 從名稱就可以看出, 他表示 HDFS 的 Client,
是整個 HDFS 的 RPC 機制的客戶端部分。我們對 HDFS 的操作,是通過 FileSsytem 調用 的
DFSClient 里面的方法。 FileSystem 是封裝了對 DFSClient 的操作,提供給用戶使用的。
4.10. HDFS 的讀數據過程分析
我們繼續在 FileSystem 類分析,讀數據使用的是 open(…)方法,我們可以看到源碼,如

在圖 5-12 中, 返回的是 DFSClient 類中 DFSDataInputStream 類, 顯而易見, 這是一個內
部類。這個內部類的構造函數,有兩個形參,第一個參數是 dfs.open(…)創建的對象。我們
看一下方法的源碼,如圖 5-13 所示。

在圖 5-13 的實現中,返回的是一個 DFSInputStream 對象。該對象中含有 NameNode 中
的數據塊信息。我們看一下這個類的構造方法源碼,如圖 5-14 所示。

在圖 5-14 中,這個構造方法中最重要的語句是第 1834 行,打開信息,從第 1840 行開
始是 openInfo()的源代碼, 截圖顯示不全。 注意第 1841 行, 是獲取數據塊的信息的。 我們查
看這一行的源代碼,如圖 5-15 所示。

從圖 5-15 中可以看到,獲取數據塊信息的方法也是通過調用 namenode 取得的。這里
的 namenode 屬性還是位於 DFSClient 中的。通過前面的分析,我們已經知道,在 DFSClient
類中的 namenode 屬性是 ClientProtocal。
至此,讀者應該能夠自己畫出類之間的調用過程了。

 


免責聲明!

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



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