远程过程调用失败_Java开发大型互联网RPC远程调用服务实现之问题处理方案
引言
RPC(Remote Procedure Call Protocol)——遠(yuǎn)程過(guò)程調(diào)用協(xié)議,它是一種通過(guò)網(wǎng)絡(luò)從遠(yuǎn)程計(jì)算機(jī)程序上請(qǐng)求服務(wù),而不需要了解底層網(wǎng)絡(luò)技術(shù)的協(xié)議。RPC協(xié)議假定某些傳輸協(xié)議的存在,如TCP或UDP,為通信程序之間攜帶信息數(shù)據(jù)。在OSI網(wǎng)絡(luò)通信模型中,RPC跨越了傳輸層和應(yīng)用層。RPC使得開發(fā)包括網(wǎng)絡(luò)分布式多程序在內(nèi)的應(yīng)用程序更加容易。
RPC采用客戶機(jī)/服務(wù)器模式。請(qǐng)求程序就是一個(gè)客戶機(jī),而服務(wù)提供程序就是一個(gè)服務(wù)器。首先,客戶機(jī)調(diào)用進(jìn)程發(fā)送一個(gè)有進(jìn)程參數(shù)的調(diào)用信息到服務(wù)進(jìn)程,然后等待應(yīng)答信息。在服務(wù)器端,進(jìn)程保持睡眠狀態(tài)直到調(diào)用信息到達(dá)為止。當(dāng)一個(gè)調(diào)用信息到達(dá),服務(wù)器獲得進(jìn)程參數(shù),計(jì)算結(jié)果,發(fā)送答復(fù)信息,然后等待下一個(gè)調(diào)用信息,最后,客戶端調(diào)用進(jìn)程接收答復(fù)信息,獲得進(jìn)程結(jié)果,然后調(diào)用執(zhí)行繼續(xù)進(jìn)行。有多種 RPC模式和執(zhí)行。
RPC 結(jié)構(gòu)
實(shí)現(xiàn) RPC 的程序包括 5 個(gè)部分:
1. User
2. User-stub
3. RPCRuntime
4. Server-stub
5. Server
RPC 調(diào)用分類
RPC 調(diào)用的分類方式有很多種。
從通信協(xié)議層面可以分為:
基于 HTTP 協(xié)議的 RPC;
基于二進(jìn)制協(xié)議的 RPC;
基于 TCP 協(xié)議的 RPC。
從是否跨平臺(tái)可分為:
單語(yǔ)言 RPC,如 RMI, Remoting;
跨平臺(tái) RPC,如 google protobuffer, restful json,http XML。
從調(diào)用過(guò)程來(lái)看,可以分為同步通信RPC和異步通信RPC:
同步 RPC:指的是客戶端發(fā)起調(diào)用后,必須等待調(diào)用執(zhí)行完成并返回結(jié)果;
異步 RPC:指客戶方調(diào)用后不關(guān)心執(zhí)行結(jié)果返回,如果客戶端需要結(jié)果,可用通過(guò)提供異步 callback 回調(diào)獲取返回信息。大部分 RPC 框架都同時(shí)支持這兩種方式的調(diào)用。
RPC 功能目標(biāo)
RPC 的主要功能目標(biāo)是讓構(gòu)建分布式計(jì)算(應(yīng)用)更容易,在提供強(qiáng)大的遠(yuǎn)程調(diào)用能力時(shí)不損失本地調(diào)用的語(yǔ)義簡(jiǎn)潔性。為實(shí)現(xiàn)該目標(biāo),RPC 框架需提供一種透明調(diào)用機(jī)制讓使用者不必顯式的區(qū)分本地調(diào)用和遠(yuǎn)程調(diào)用,在前文《淺出篇》中給出了一種實(shí)現(xiàn)結(jié)構(gòu),基于 stub 的結(jié)構(gòu)來(lái)實(shí)現(xiàn)。下面我們將具體細(xì)化 stub 結(jié)構(gòu)的實(shí)現(xiàn)。
Java RPC 實(shí)現(xiàn)
在進(jìn)一步拆解了組件并劃分了職責(zé)之后,這里以一個(gè)最簡(jiǎn)單 Java RPC 框架實(shí)現(xiàn)為例,對(duì) RPC 具體邏輯進(jìn)行分析。
RPC 框架服務(wù)發(fā)布代碼:
服務(wù)端發(fā)布服務(wù)的代碼如上,首先校驗(yàn)傳入的端口和服務(wù)是否合法,然后開啟一個(gè) socket 監(jiān)聽,這兒為了簡(jiǎn)便,沒(méi)有采用 NIO 方式,同時(shí)直接采用 java 的序列化方式,將傳入的數(shù)據(jù)通過(guò)反射取出調(diào)用的方法和參數(shù),本地執(zhí)行后將運(yùn)行結(jié)果通過(guò) socket 套接字返回給客戶端。RPC 框架服務(wù)調(diào)用代碼:框架中客戶端調(diào)用的代碼中,首先校驗(yàn)對(duì)應(yīng)的端口和主機(jī)是否合法,然后通過(guò)動(dòng)態(tài)代理生成一個(gè)代理對(duì)象,在代理對(duì)象的方法中,攔截調(diào)用,通過(guò)建立 socket 連接,將方法和參數(shù)傳遞到遠(yuǎn)端執(zhí)行并獲取遠(yuǎn)程執(zhí)行返回結(jié)果。
RPC 調(diào)用測(cè)試:如上圖所示,服務(wù)器端發(fā)布一個(gè)接口服務(wù) HelloService,客戶端成功通過(guò) RPC 調(diào)用。
怎么做到遠(yuǎn)程服務(wù)調(diào)用?
怎么封裝通信細(xì)節(jié)才能讓用戶像以本地調(diào)用方式調(diào)用遠(yuǎn)程服務(wù)呢?對(duì)java來(lái)說(shuō)就是使用代理!java代理有兩種方式:1) jdk 動(dòng)態(tài)代理;2)字節(jié)碼生成。盡管字節(jié)碼生成方式實(shí)現(xiàn)的代理更為強(qiáng)大和高效,但代碼不易維護(hù),大部分公司實(shí)現(xiàn)RPC框架時(shí)還是選擇動(dòng)態(tài)代理方式。
下面簡(jiǎn)單介紹下動(dòng)態(tài)代理怎么實(shí)現(xiàn)我們的需求。我們需要實(shí)現(xiàn)RPCProxyClient代理類,代理類的invoke方法中封裝了與遠(yuǎn)端服務(wù)通信的細(xì)節(jié),消費(fèi)方首先從RPCProxyClient獲得服務(wù)提供方的接口,當(dāng)執(zhí)行helloWorldService.sayHello(“test”)方法時(shí)就會(huì)調(diào)用invoke方法。
Java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
publicclassRPCProxyClient implementsjava.lang.reflect.InvocationHandler{
privateObjectobj;
publicRPCProxyClient(Objectobj){
this.obj=obj;
}
/**
* 得到被代理對(duì)象;
*/
publicstaticObjectgetProxy(Objectobj){
returnjava.lang.reflect.Proxy.newProxyInstance(obj.getClass().getClassLoader(),
obj.getClass().getInterfaces(),newRPCProxyClient(obj));
}
/**
* 調(diào)用此方法執(zhí)行
*/
publicObjectinvoke(Objectproxy,Method method,Object[]args)
throwsThrowable{
//結(jié)果參數(shù);
Objectresult=newObject();
// ...執(zhí)行通信相關(guān)邏輯
// ...
returnresult;
}
}
Java
1
2
3
4
5
6
publicclassTest{
publicstaticvoidmain(String[]args){
HelloWorldService helloWorldService=(HelloWorldService)RPCProxyClient.getProxy(HelloWorldService.class);
helloWorldService.sayHello("test");
}
}
異常處理
無(wú)論 RPC 怎樣努力把遠(yuǎn)程調(diào)用偽裝的像本地調(diào)用,但它們依然有很大的不同點(diǎn),而且有一些異常情況是在本地調(diào)用時(shí)絕對(duì)不會(huì)碰到的。在說(shuō)異常處理之前,我們先比較下本地調(diào)用和 RPC調(diào)用的一些差異:
正是這些區(qū)別決定了使用 RPC 時(shí)需要更多考量。
當(dāng)調(diào)用遠(yuǎn)程接口拋出異常時(shí),異常可能是一個(gè)業(yè)務(wù)異常, 也可能是 RPC 框架拋出的運(yùn)行時(shí)異常(如:網(wǎng)絡(luò)中斷等)。
業(yè)務(wù)異常表明服務(wù)方已經(jīng)執(zhí)行了調(diào)用,可能因?yàn)槟承┰驅(qū)е挛茨苷?zhí)行, 而 RPC 運(yùn)行時(shí)異常則有可能服務(wù)方根本沒(méi)有執(zhí)行,對(duì)調(diào)用方而言的異常處理策略自然需要區(qū)分。
由于 RPC 固有的消耗相對(duì)本地調(diào)用高出幾個(gè)數(shù)量級(jí),
本地調(diào)用的固有消耗是納秒級(jí),而 RPC 的固有消耗是在毫秒級(jí)。
那么對(duì)于過(guò)于輕量的計(jì)算任務(wù)就并不合適導(dǎo)出遠(yuǎn)程接口由獨(dú)立的進(jìn)程提供服務(wù),
只有花在計(jì)算任務(wù)上時(shí)間遠(yuǎn)遠(yuǎn)高于 RPC 的固有消耗才值得導(dǎo)出為遠(yuǎn)程接口提供服務(wù)。
總結(jié)
以 上就是我對(duì)Java開發(fā)大型互聯(lián)網(wǎng)RPC遠(yuǎn)程調(diào)用服務(wù)實(shí)現(xiàn)之問(wèn)題處理方案 問(wèn)題及其優(yōu)化總結(jié),分享給大家,覺(jué)得收獲的話可以點(diǎn)個(gè)關(guān)注收藏轉(zhuǎn)發(fā)一波喔,謝謝大佬們支持!
最后,每一位讀到這里的網(wǎng)友,感謝你們能耐心地看完。希望在成為一名更優(yōu)秀的Java程序員的道路上,我們可以一起學(xué)習(xí)、一起進(jìn)步!都能贏取白富美,走向架構(gòu)師的人生巔峰!
想了解學(xué)習(xí)Java方面的技術(shù)內(nèi)容以及Java技術(shù)視頻的內(nèi)容可加群:722040762 驗(yàn)證碼:頭條(06 必過(guò))歡迎大家的加入喲!
總結(jié)
以上是生活随笔為你收集整理的远程过程调用失败_Java开发大型互联网RPC远程调用服务实现之问题处理方案的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: win8怎么bios设置还原系统还原 w
- 下一篇: java仿qq gui_Java仿QQ登