RPC原理介紹

RPC功能介紹
RPC (Remote Procedure Call)的主要功能目標是讓構建分布式計算(應用)更容易盏求,在提供強大的遠程調(diào)用能力時不損失本地調(diào)用的語義簡潔性仙畦。 為實現(xiàn)該目標钳幅,RPC 框架需提供一種透明調(diào)用機制讓使用者不必顯式的區(qū)分本地調(diào)用和遠程調(diào)用。  
RPC采用C/S模式催享。請求程序就是一個客戶機,而服務提供程序就是一個服務器哟绊。首先因妙,客戶機調(diào)用進程發(fā)送一個有進程參數(shù)的調(diào)用信息到服務進程,然后等待應答信息票髓。在服務器端攀涵,進程保持睡眠狀態(tài)直到調(diào)用信息的到達為止。當一個調(diào)用信息到達洽沟,服務器獲得進程參數(shù)以故,計算結果發(fā)送答復信息,然后等待下一個調(diào)用信息玲躯。最后据德,客戶端調(diào)用進程接收答復信息,獲得進程結果跷车,然后調(diào)用執(zhí)行繼續(xù)進行棘利。

RPC調(diào)用流程


Paste_Image.png

1)服務消費方(client)調(diào)用以本地調(diào)用方式調(diào)用服務;
2)client stub接收到調(diào)用后負責將方法朽缴、參數(shù)等組裝成能夠進行網(wǎng)絡傳輸?shù)南Ⅲw善玫;
3)client stub找到服務地址,并將消息發(fā)送到服務端密强;
4)server stub收到消息后進行解碼茅郎;
5)server stub根據(jù)解碼結果調(diào)用本地的服務;
6)本地服務執(zhí)行并將結果返回給server stub或渤;
7)server stub將返回結果打包成消息并發(fā)送至消費方系冗;
8)client stub接收到消息,并進行解碼薪鹦;
9)服務消費方得到最終結果掌敬。

RPC的任務就是封裝2-8步驟惯豆,使調(diào)用過程對調(diào)用方透明。

代理
java使用代理的方式封裝通信細節(jié)奔害。代理類的invoke方法中封裝了與遠端服務通信的細節(jié)楷兽,調(diào)用方首先從RPCProxyClient獲得服務提供方的接口,當執(zhí)行helloWorldService.sayHello(“test”)方法時就會調(diào)用invoke方法华临。

public class RPCProxyClient implements java.lang.reflect.InvocationHandler{
    private Object obj;
    public RPCProxyClient(Object obj){
        this.obj=obj;
    }
    /**
     * 得到被代理對象;
     */
    public static Object getProxy(Object obj){
        return java.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),
            obj.getClass().getInterfaces(), new RPCProxyClient(obj));
    }

    /**
     * 調(diào)用此方法執(zhí)行
     */
    public Object invoke(Object proxy, Method method, Object[] args)
        throws Throwable {
        //結果參數(shù);
        Object result = new Object();
        // ...執(zhí)行通信相關邏輯
        // ...
        return result;
    }
}

public class Test {
    public static void main(String[] args) {
        HelloWorldService helloWorldService = (HelloWorldService)RPCProxyClient.getProxy(HelloWorldService.class);
        helloWorldService.sayHello("test");
    }
}

序列化
客戶端的請求消息結構一般包括以下內(nèi)容:
(1)接口名和方法名
(2)參數(shù)類型和參數(shù)值
(3)超時時間
(5)requestID
服務端返回的消息結構一般包括以下內(nèi)容:
(1)返回值
(2)狀態(tài)碼
(3)requestID
確定了消息的數(shù)據(jù)結構后芯杀,下一步就是要考慮序列化與反序列化了。序列化就是將數(shù)據(jù)結構或?qū)ο筠D換成二進制串的過程雅潭,也就是編碼的過程揭厚。反序列化就是將在序列化過程中所生成的二進制串轉換成數(shù)據(jù)結構或者對象的過程。
從RPC的角度來選擇序列化方案寻馏,主要考慮(1)通用性棋弥,是否能支持比較復雜的數(shù)據(jù)結構;(2)可擴展性诚欠,增加或刪除字段能不影響老的服務;(3)性能漾岳,從時間和空間兩個維度去衡量序列化效率和序列化后的字節(jié)長度轰绵。
目前國內(nèi)各大互聯(lián)網(wǎng)公司廣泛使用hessian、protobuf尼荆、thrift左腔、avro等成熟的序列化解決方案來搭建RPC框架。
通信
消息體被編碼之后是需要將編碼后的請求消息傳輸?shù)椒辗酵比濉5讓拥腞PC傳輸通道可以是TCP也可以是UDP液样。
如何保證返回結果的有序性
如果有多個線程同時進行遠程方法調(diào)用,這時建立在client server之間的socket連接上會有很多雙方發(fā)送的消息傳遞巧还,前后順序也可能是隨機的鞭莽,server處理完結果后,將結果消息發(fā)送給client麸祷,client收到很多消息澎怒,怎么知道哪個消息結果是原先哪個線程調(diào)用的?
線程A和線程B同時向client socket發(fā)送請求requestA和requestB阶牍,socket先后將requestB和requestA發(fā)送至server喷面,而server可能將responseA先返回,盡管requestA請求到達時間更晚走孽。我們需要一種機制保證responseA返回給ThreadA惧辈,responseB返回給ThreadB。

Paste_Image.png

1)client線程每次通過socket調(diào)用遠程接口前磕瓷,生成一個唯一的ID盒齿,即requestID(requestID必需保證在一個Socket連接里面是唯一的),一般常常使用AtomicLong從0開始累計數(shù)字生成唯一ID;
2)將處理結果的回調(diào)對象callback县昂,存放到全局ConcurrentHashMap里面put(requestID, callback)肮柜;
3)當client線程發(fā)送消息后,緊接著執(zhí)行callback的get()方法試圖獲取遠程返回的結果倒彰。在get()內(nèi)部审洞,則使用synchronized獲取回調(diào)對象callback的鎖。先檢測是否已經(jīng)獲取到結果待讳,如果沒有芒澜,則調(diào)用callback的wait()方法,釋放callback上的鎖创淡,讓當前線程處于等待狀態(tài)痴晦。
4)服務端接收到請求并處理后,將response結果(此結果中包含了前面的requestID)發(fā)送給客戶端琳彩,客戶端socket連接上專門監(jiān)聽消息的線程收到消息誊酌,分析結果取到requestID,再從前面的ConcurrentHashMap里面get(requestID)露乏,從而找到callback對象碧浊。再用synchronized獲取callback上的鎖,將方法調(diào)用結果設置到callback對象里瘟仿,再調(diào)用callback.notifyAll()喚醒前面處于等待狀態(tài)的線程箱锐。

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市劳较,隨后出現(xiàn)的幾起案子驹止,更是在濱河造成了極大的恐慌,老刑警劉巖观蜗,帶你破解...
    沈念sama閱讀 210,978評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件臊恋,死亡現(xiàn)場離奇詭異,居然都是意外死亡嫂便,警方通過查閱死者的電腦和手機捞镰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,954評論 2 384
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來毙替,“玉大人岸售,你說我怎么就攤上這事〕Щ” “怎么了凸丸?”我有些...
    開封第一講書人閱讀 156,623評論 0 345
  • 文/不壞的土叔 我叫張陵,是天一觀的道長袱院。 經(jīng)常有香客問我屎慢,道長瞭稼,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,324評論 1 282
  • 正文 為了忘掉前任腻惠,我火速辦了婚禮环肘,結果婚禮上,老公的妹妹穿的比我還像新娘集灌。我一直安慰自己悔雹,他們只是感情好,可當我...
    茶點故事閱讀 65,390評論 5 384
  • 文/花漫 我一把揭開白布欣喧。 她就那樣靜靜地躺著腌零,像睡著了一般。 火紅的嫁衣襯著肌膚如雪唆阿。 梳的紋絲不亂的頭發(fā)上益涧,一...
    開封第一講書人閱讀 49,741評論 1 289
  • 那天,我揣著相機與錄音驯鳖,去河邊找鬼闲询。 笑死,一個胖子當著我的面吹牛浅辙,可吹牛的內(nèi)容都是我干的嘹裂。 我是一名探鬼主播,決...
    沈念sama閱讀 38,892評論 3 405
  • 文/蒼蘭香墨 我猛地睜開眼摔握,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了丁寄?” 一聲冷哼從身側響起氨淌,我...
    開封第一講書人閱讀 37,655評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎伊磺,沒想到半個月后盛正,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,104評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡屑埋,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,451評論 2 325
  • 正文 我和宋清朗相戀三年豪筝,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片摘能。...
    茶點故事閱讀 38,569評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡续崖,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出团搞,到底是詐尸還是另有隱情严望,我是刑警寧澤,帶...
    沈念sama閱讀 34,254評論 4 328
  • 正文 年R本政府宣布逻恐,位于F島的核電站像吻,受9級特大地震影響峻黍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜拨匆,卻給世界環(huán)境...
    茶點故事閱讀 39,834評論 3 312
  • 文/蒙蒙 一姆涩、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧惭每,春花似錦骨饿、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,725評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至览爵,卻和暖如春置鼻,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蜓竹。 一陣腳步聲響...
    開封第一講書人閱讀 31,950評論 1 264
  • 我被黑心中介騙來泰國打工箕母, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人俱济。 一個月前我還...
    沈念sama閱讀 46,260評論 2 360
  • 正文 我出身青樓嘶是,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蛛碌。 傳聞我的和親對象是個殘疾皇子聂喇,可洞房花燭夜當晚...
    茶點故事閱讀 43,446評論 2 348

推薦閱讀更多精彩內(nèi)容