以下文章來(lái)源于公眾號(hào)架構(gòu)研究所 ,作者架構(gòu)師易哥
問(wèn):既然有 HTTP 請(qǐng)求,為什么還要用 RPC 調(diào)用?
首先 RPC 框架配置復(fù)雜,如果走 HTTP 請(qǐng)求同樣也能做到相同功能,而且配置可以幾乎為零配置。項(xiàng)目也不用引用太多的包。雖然如果單純用 RPC,可以不用類似于 Servlet 的 Web 標(biāo)準(zhǔn)。
首先,實(shí)名贊揚(yáng)題主的問(wèn)題。這個(gè)問(wèn)題非常好。
其次,實(shí)名反對(duì)各個(gè)上來(lái)就講RPC好而HTTP不好的答案。因?yàn)椋}主的觀點(diǎn)非常對(duì)。
HTTP協(xié)議,以其中的Restful規(guī)范為代表,其優(yōu)勢(shì)很大。它可讀性好,且可以得到防火墻的支持、跨語(yǔ)言的支持。而且,在去年的報(bào)告中,Restful大有超過(guò)RPC的趨勢(shì)。
本想引用下報(bào)告內(nèi)容,無(wú)奈最近由于某些原因,KeXueShangWang被Qiang了。等我日后出墻時(shí),再做補(bǔ)充。
但是HTTP也有其缺點(diǎn),這是與其優(yōu)點(diǎn)相對(duì)應(yīng)的。首先是有用信息占比少,畢竟HTTP工作在第七層,包含了大量的HTTP頭等信息。其次是效率低,還是因?yàn)榈谄邔拥木壒省_€有,其可讀性似乎沒(méi)有必要,因?yàn)槲覀兛梢砸刖W(wǎng)關(guān)增加可讀性。此外,使用HTTP協(xié)議調(diào)用遠(yuǎn)程方法比較復(fù)雜,要封裝各種參數(shù)名和參數(shù)值。
而RPC則與HTTP互補(bǔ),我們?cè)敿?xì)介紹下。看完這篇回答,能讓你對(duì)RPC的產(chǎn)生、原理、實(shí)現(xiàn)代碼都有著清晰的了解。這樣,也能在業(yè)務(wù)系統(tǒng)中,在RPC和HTTP之間做好抉擇。
但需要再說(shuō)一句,不是說(shuō)RPC好,也不是說(shuō)HTTP好,兩者各有千秋,還在比拼中。
要問(wèn)我站誰(shuí)?我根據(jù)業(yè)務(wù)場(chǎng)景,靈活站位……
RPC的英文全稱是Remote Procedure Call,翻譯為中文叫“遠(yuǎn)程過(guò)程調(diào)用”。其中稍顯晦澀的其實(shí)就是“過(guò)程”,過(guò)程其實(shí)就是方法。所以,可以把RPC理解為“遠(yuǎn)程方法調(diào)用”。
要了解遠(yuǎn)程過(guò)程調(diào)用,那先理解過(guò)程調(diào)用。非常簡(jiǎn)單,如下圖,就是調(diào)用一個(gè)方法。這太常見(jiàn)了,不多解釋。
而在分布式系統(tǒng)中,因?yàn)槊總€(gè)服務(wù)的邊界都很小,很有可能調(diào)用別的服務(wù)提供的方法。這就出現(xiàn)了服務(wù)A調(diào)用服務(wù)B中方法的需求,即遠(yuǎn)程過(guò)程調(diào)用。
要想讓服務(wù)A調(diào)用服務(wù)B中的方法,最先想到的就是通過(guò)HTTP請(qǐng)求實(shí)現(xiàn)。是的,這是很常見(jiàn)的,例如服務(wù)B暴露Restful接口,然后讓服務(wù)A調(diào)用它的接口?;赗estful的調(diào)用方式因?yàn)榭勺x性好(服務(wù)B暴露出的是Restful接口,可讀性當(dāng)然好)而且HTTP請(qǐng)求可以通過(guò)各種防火墻,因此非常不錯(cuò)。
然而,如前面所述,基于Restful的遠(yuǎn)程過(guò)程調(diào)用有著明顯的缺點(diǎn),主要是效率低、封裝調(diào)用復(fù)雜。當(dāng)存在大量的服務(wù)間調(diào)用時(shí),這些缺點(diǎn)變得更為突出。
服務(wù)A調(diào)用服務(wù)B的過(guò)程是應(yīng)用間的內(nèi)部過(guò)程,犧牲可讀性提升效率、易用性是可取的?;谶@種思路,RPC產(chǎn)生了。
通常,RPC要求在調(diào)用方中放置被調(diào)用的方法的接口。調(diào)用方只要調(diào)用了這些接口,就相當(dāng)于調(diào)用了被調(diào)用方的實(shí)際方法,十分易用。于是,調(diào)用方可以像調(diào)用內(nèi)部接口一樣調(diào)用遠(yuǎn)程的方法,而不用封裝參數(shù)名和參數(shù)值等操作。
那要想實(shí)現(xiàn)這個(gè)過(guò)程該怎么辦呢?別急,咱們一步一步來(lái)。
首先,調(diào)用方調(diào)用的是接口,必須得為接口構(gòu)造一個(gè)假的實(shí)現(xiàn)。顯然,要使用動(dòng)態(tài)代理。這樣,調(diào)用方的調(diào)用就被動(dòng)態(tài)代理接收到了。
第二,動(dòng)態(tài)代理接收到調(diào)用后,應(yīng)該想辦法調(diào)用遠(yuǎn)程的實(shí)際實(shí)現(xiàn)。這包括下面幾步:
識(shí)別具體要調(diào)用的遠(yuǎn)程方法的IP、端口
將調(diào)用方法的入?yún)⑦M(jìn)行序列化
通過(guò)通信將請(qǐng)求發(fā)送到遠(yuǎn)程的方法中
這樣,遠(yuǎn)程的服務(wù)就接收到了調(diào)用方的請(qǐng)求。它應(yīng)該:
反序列化各個(gè)調(diào)用參數(shù)
定位到實(shí)際要調(diào)用的方法,然后輸入?yún)?shù),執(zhí)行方法
按照調(diào)用的路徑返回調(diào)用的結(jié)果
整個(gè)過(guò)程如下所示。
這樣,RPC操作就完成了。
調(diào)用方調(diào)用內(nèi)部的一個(gè)方法,但是被RPC框架偷梁換柱為遠(yuǎn)程的一個(gè)方法。之間的通信數(shù)據(jù)可讀性不需要好,只需要RPC框架能讀懂即可,因此效率可以更高。通常使用UDP或者TCP作為通訊協(xié)議,當(dāng)然也可以使用HTTP。例如下面的示例中,為了保證實(shí)現(xiàn)最簡(jiǎn)單,就用了HTTP進(jìn)行通信。
講到這里,RPC的產(chǎn)生原因、原理應(yīng)該清楚了。為了讓大家真的明白,我寫(xiě)了一個(gè)真的是最最簡(jiǎn)單的RPC實(shí)現(xiàn)。把它放到了:
https://github.com/yeecode/EasyRPC
它包含一個(gè)客戶端,一個(gè)服務(wù)端??蛻舳酥灰{(diào)用自身內(nèi)部的接口,就通過(guò)這個(gè)小的RPC實(shí)現(xiàn)調(diào)用到了服務(wù)端的方法。
下面是客戶端的代碼,看著類有點(diǎn)多,其實(shí)代碼不長(zhǎng)。其中的RPC代碼完成完成動(dòng)態(tài)代理、遠(yuǎn)程調(diào)用參數(shù)序列化、遠(yuǎn)程調(diào)用發(fā)起、遠(yuǎn)程調(diào)用結(jié)果反序列化的工作。
下面是服務(wù)端的代碼,代碼更少,完成遠(yuǎn)程調(diào)用接收、調(diào)用參數(shù)反序列化、調(diào)用實(shí)際觸發(fā)、調(diào)用結(jié)果序列化的工作。
這樣,一個(gè)RPC小框架就做完了,并不復(fù)雜。
所以,不要被RPC嚇到,它就是讓一個(gè)應(yīng)用調(diào)用另一個(gè)應(yīng)用中方法的一種實(shí)現(xiàn)方式。與調(diào)用遠(yuǎn)程接口區(qū)別不大,條條大路通羅馬。
再說(shuō)一次,不是說(shuō)RPC好,也不是說(shuō)HTTP好,兩者各有千秋。本質(zhì)上,兩者是可讀性和效率之間的抉擇,通用性和易用性之間的抉擇。最終誰(shuí)能發(fā)展更好,很難說(shuō)。
要問(wèn)我站誰(shuí)?我根據(jù)業(yè)務(wù)場(chǎng)景,靈活站位……
如果還有什么沒(méi)說(shuō)清楚了,可以留言再問(wèn)。
該回答轉(zhuǎn)載自我的知乎,歡迎前往知乎關(guān)注我.