hbase rpc這點事


年前的時候系統梳理了一下hbase rpc的實現,並且對組里的小伙伴做了一次分享。趁着熱乎勁還沒完全消失殆盡,准備趕緊記錄下來。

hbase中rpc概況

作為一個分布式系統,hbase的設計是典型的master-salve架構。hbase中主要有master,regionserver,client這三個角色。這三個角色之間rpc的調用關系可以用下圖來描述。

client

client有很多,比方說:hbase shell, Java client API等。client沒有提供任何rpc服務,它只是調用RegionServer或者master提供的服務。

Master

master主要實現了MasterService和RegionServerStatus協議,分別供Client和RegionServer調用。

MasterService

MasterService主要定義了獲取集群狀態,以及獲取表的元信息,添加/刪除列,assign region, enable/disable table,負載均衡等DML相關的一些服務。而Master提供了對這些服務的實現,並且供客戶端去調用。比方說,當我們在hbase shell中運行enable/disable table等相關的命令時,client會首先將該rpc請求發送到master。

RegionServerStatus

RegionServerStatus主要定義了regionserver向master匯報集群狀態,regionserver啟動向master發送rpc請求等相關的服務,而master根據這些rpc請求信息,可以了解整個集群中regionserver的狀態。

ReginServer

RegionServer主要實現了AdminService和ClientService協議,供client端調用。而與此同時,ReginServer也會調用RegionServerStatus服務,將相關信息匯報給master。

AdminService

AmdinService主要定義了獲取table Regin信息,操作region(Open,Flush,Split,Compact, Merge等)相關服務。

ClientService

ClientService主要定了獲取數據,更新,添加數據,Scan等相關的服務。

問題

通過上圖,我們發現Master分別提供了對Client和RegionServer的Rpc服務,但是RegionServer卻只提供了對client的Rpc服務,而沒有提供對Master的rpc的服務。那么當Master怎么向Client發送請求的呢?比方說master啟動負載均衡時,需要讓regionServer移動region。
答案其實就是通過zookeeper。那為什么會這樣呢?
對於整個問題一個可能的解釋是:當Master向RegionServer傳遞信息時,可能需要向多台reginserver傳遞信息。而通過zookeeper中的node簡單變化主動通知regionserver可能更好。(分享時,組里的小伙伴給出的解析,感覺確實是這樣)。

Client端rpc實現

使用方式

client發起遠程調用時,首先生成一個RpcClient的實例(具體實現類是RpcClientImpl),然后調用call參數(傳入方法名稱,參數等)。代碼實例如下:

1
2
RpcClient client = new RpcClientImpl(conf, HConstants.CLUSTER_ID_DEFAULT);
client.call(...)

 

client rpc流程

client端rpc實現的主要流程如下圖:

主要分為以下幾個步驟:
1,client調用call方法后,首先會把傳入的參數封裝成Call對象(該對象包含方法名稱,調用參數,連接地址等信息),並且根據該對象獲取連接信息。client端有一個Map對象connections,緩存了連接信息。如果之前有對應的連接則直接獲取,否則新建連接並且緩存起來。
2,client端通過調用sendCall函數,生成CallFuture對象,並且將該對象push到CallsToWrite隊列中。然后便一直等待本地調用是否成功返回,無論結果如何都將刪除之前在callSender中創建的CallFuture對象,然后把結果包裝成Pair<message, cellscanner="">返回。
3,另一方面,CallSender線程持續從CallsToWrite隊列中獲取步驟2中push進去的對象,生成Request請求發送到server端,並且把當前的call對象push到connection的calls中。
4,此后,Connection中run方法持續從步驟3的calls隊列讀取已發送的請求,檢查結果是否從server返回,一旦返回將構造對應的response保存到call中。

Server端Rpc實現

server的實現相比較client端要復雜很多。server端rpc的實現的原理主要是基於異步事件響應設計。主要流程如下圖所示:

1,server端的實現邏輯主要封裝在rpcserver對象中,在該對象中,首先有一個Listener對象,負責監控連接請求,一旦有連接,Lister會選擇一個Reader,並且在新建的連接上注冊OP_READ時間,封裝中Connection對象。一般只有一個Listener對象。
2,Reader首先從連接中讀取數據,最終構造成callRunner,交由調度器調度。rpcserver對象中一般會有多個Reader對象。
3,根據調度器選擇的一個callRunner對象,調用CallRunner:Run->RpcServer:call,從而調用具體函數的實現。
4,函數返回結果后,包裝成response對象,並且通過doResponse函數將當前的Call push到responseQueue中, 而且將當前conn Responder需要寫到writingCons中。
5,注冊步驟4中writingCons中連接的OP_WRITE事件,從responseQueue中獲取call,並且進行處理,將結果的byte流發送出出去。

調度策略

調度的基本設計圖如下:

在server實現過程中,講到調度器,hbase rpc實現了兩種調度器(FifoRpcScheduler和SimpleRpcScheduler)。FifoRpcScheduler會直接將CallRunner對象放到線程池中去執行。而SimpleRpcScheduler,會分成三種不同的executor,對於不同的請求,使用的不同的executor去執行。

小結

通過對hbase rpc的梳理總結,算是對hbase rpc有了較為深入的理解。rpc可以認為是hbase這個系統的血液循環系統,熟悉了rpc,對於學習hbase其他部分的實現原理也大有裨益。


免責聲明!

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



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