hbase rpc这点事
年前的時(shí)候系統(tǒng)梳理了一下hbase rpc的實(shí)現(xiàn),并且對組里的小伙伴做了一次分享。趁著熱乎勁還沒完全消失殆盡,準(zhǔn)備趕緊記錄下來。
hbase中rpc概況
作為一個(gè)分布式系統(tǒng),hbase的設(shè)計(jì)是典型的master-salve架構(gòu)。hbase中主要有master,regionserver,client這三個(gè)角色。這三個(gè)角色之間rpc的調(diào)用關(guān)系可以用下圖來描述。
client
client有很多,比方說:hbase shell, Java client API等。client沒有提供任何rpc服務(wù),它只是調(diào)用RegionServer或者master提供的服務(wù)。
Master
master主要實(shí)現(xiàn)了MasterService和RegionServerStatus協(xié)議,分別供Client和RegionServer調(diào)用。
MasterService
MasterService主要定義了獲取集群狀態(tài),以及獲取表的元信息,添加/刪除列,assign region, enable/disable table,負(fù)載均衡等DML相關(guān)的一些服務(wù)。而Master提供了對這些服務(wù)的實(shí)現(xiàn),并且供客戶端去調(diào)用。比方說,當(dāng)我們在hbase shell中運(yùn)行enable/disable table等相關(guān)的命令時(shí),client會首先將該rpc請求發(fā)送到master。
RegionServerStatus
RegionServerStatus主要定義了regionserver向master匯報(bào)集群狀態(tài),regionserver啟動向master發(fā)送rpc請求等相關(guān)的服務(wù),而master根據(jù)這些rpc請求信息,可以了解整個(gè)集群中regionserver的狀態(tài)。
ReginServer
RegionServer主要實(shí)現(xiàn)了AdminService和ClientService協(xié)議,供client端調(diào)用。而與此同時(shí),ReginServer也會調(diào)用RegionServerStatus服務(wù),將相關(guān)信息匯報(bào)給master。
AdminService
AmdinService主要定義了獲取table Regin信息,操作region(Open,Flush,Split,Compact, Merge等)相關(guān)服務(wù)。
ClientService
ClientService主要定了獲取數(shù)據(jù),更新,添加數(shù)據(jù),Scan等相關(guān)的服務(wù)。
問題
通過上圖,我們發(fā)現(xiàn)Master分別提供了對Client和RegionServer的Rpc服務(wù),但是RegionServer卻只提供了對client的Rpc服務(wù),而沒有提供對Master的rpc的服務(wù)。那么當(dāng)Master怎么向Client發(fā)送請求的呢?比方說master啟動負(fù)載均衡時(shí),需要讓regionServer移動region。
答案其實(shí)就是通過zookeeper。那為什么會這樣呢?
對于整個(gè)問題一個(gè)可能的解釋是:當(dāng)Master向RegionServer傳遞信息時(shí),可能需要向多臺reginserver傳遞信息。而通過zookeeper中的node簡單變化主動通知regionserver可能更好。(分享時(shí),組里的小伙伴給出的解析,感覺確實(shí)是這樣)。
Client端rpc實(shí)現(xiàn)
使用方式
client發(fā)起遠(yuǎn)程調(diào)用時(shí),首先生成一個(gè)RpcClient的實(shí)例(具體實(shí)現(xiàn)類是RpcClientImpl),然后調(diào)用call參數(shù)(傳入方法名稱,參數(shù)等)。代碼實(shí)例如下:
| 1 2 | RpcClient client = new RpcClientImpl(conf, HConstants.CLUSTER_ID_DEFAULT); client.call(...) |
?
client rpc流程
client端rpc實(shí)現(xiàn)的主要流程如下圖:
主要分為以下幾個(gè)步驟:
1,client調(diào)用call方法后,首先會把傳入的參數(shù)封裝成Call對象(該對象包含方法名稱,調(diào)用參數(shù),連接地址等信息),并且根據(jù)該對象獲取連接信息。client端有一個(gè)Map對象connections,緩存了連接信息。如果之前有對應(yīng)的連接則直接獲取,否則新建連接并且緩存起來。
2,client端通過調(diào)用sendCall函數(shù),生成CallFuture對象,并且將該對象push到CallsToWrite隊(duì)列中。然后便一直等待本地調(diào)用是否成功返回,無論結(jié)果如何都將刪除之前在callSender中創(chuàng)建的CallFuture對象,然后把結(jié)果包裝成Pair<message, cellscanner="">返回。
3,另一方面,CallSender線程持續(xù)從CallsToWrite隊(duì)列中獲取步驟2中push進(jìn)去的對象,生成Request請求發(fā)送到server端,并且把當(dāng)前的call對象push到connection的calls中。
4,此后,Connection中run方法持續(xù)從步驟3的calls隊(duì)列讀取已發(fā)送的請求,檢查結(jié)果是否從server返回,一旦返回將構(gòu)造對應(yīng)的response保存到call中。
Server端Rpc實(shí)現(xiàn)
server的實(shí)現(xiàn)相比較client端要復(fù)雜很多。server端rpc的實(shí)現(xiàn)的原理主要是基于異步事件響應(yīng)設(shè)計(jì)。主要流程如下圖所示:
1,server端的實(shí)現(xiàn)邏輯主要封裝在rpcserver對象中,在該對象中,首先有一個(gè)Listener對象,負(fù)責(zé)監(jiān)控連接請求,一旦有連接,Lister會選擇一個(gè)Reader,并且在新建的連接上注冊O(shè)P_READ時(shí)間,封裝中Connection對象。一般只有一個(gè)Listener對象。
2,Reader首先從連接中讀取數(shù)據(jù),最終構(gòu)造成callRunner,交由調(diào)度器調(diào)度。rpcserver對象中一般會有多個(gè)Reader對象。
3,根據(jù)調(diào)度器選擇的一個(gè)callRunner對象,調(diào)用CallRunner:Run->RpcServer:call,從而調(diào)用具體函數(shù)的實(shí)現(xiàn)。
4,函數(shù)返回結(jié)果后,包裝成response對象,并且通過doResponse函數(shù)將當(dāng)前的Call push到responseQueue中, 而且將當(dāng)前conn Responder需要寫到writingCons中。
5,注冊步驟4中writingCons中連接的OP_WRITE事件,從responseQueue中獲取call,并且進(jìn)行處理,將結(jié)果的byte流發(fā)送出出去。
調(diào)度策略
調(diào)度的基本設(shè)計(jì)圖如下:
在server實(shí)現(xiàn)過程中,講到調(diào)度器,hbase rpc實(shí)現(xiàn)了兩種調(diào)度器(FifoRpcScheduler和SimpleRpcScheduler)。FifoRpcScheduler會直接將CallRunner對象放到線程池中去執(zhí)行。而SimpleRpcScheduler,會分成三種不同的executor,對于不同的請求,使用的不同的executor去執(zhí)行。
小結(jié)
通過對hbase rpc的梳理總結(jié),算是對hbase rpc有了較為深入的理解。rpc可以認(rèn)為是hbase這個(gè)系統(tǒng)的血液循環(huán)系統(tǒng),熟悉了rpc,對于學(xué)習(xí)hbase其他部分的實(shí)現(xiàn)原理也大有裨益。
轉(zhuǎn)載于:https://www.cnblogs.com/superhedantou/p/6476421.html
總結(jié)
以上是生活随笔為你收集整理的hbase rpc这点事的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 02:输出最高分数的学生姓名
- 下一篇: 直流电机基本系统模型