微服務(wù)調(diào)用為啥用RPC框架,Http不更簡單嗎?
背景
在一次的面試交談中,聊到業(yè)務(wù)實現(xiàn)的技術(shù)架構(gòu)。不管系統(tǒng)大小,一般都是微服務(wù)的架構(gòu),所以就產(chǎn)生了一個問題,為什么服務(wù)之間調(diào)用,選擇用RPC,http 不也能實現(xiàn)服務(wù)之間的通信嗎?怎么不用呢?或者 RPC 比 http 好在哪里?
什么是RPC
提到RPC(Remote Procedure Call),就躲不開提到分布式,這個促使RPC誕生的領(lǐng)域。
假設(shè)你有一個Calculator,以及它的實現(xiàn)類CalculatorImpl,那么單體應(yīng)用時,要調(diào)用Calculator的add方法來執(zhí)行一個加運算,你可以方法中直接使用,因為在同一個地址空間,或者說在同一塊內(nèi)存,這個稱為本地函數(shù)調(diào)用。
現(xiàn)在,將系統(tǒng)改造為分布式應(yīng)用,接口調(diào)用和實現(xiàn)分別在兩個子系統(tǒng)內(nèi),
服務(wù)A里頭并沒有CalculatorImpl這個類,那它要怎樣調(diào)用服務(wù)B的CalculatorImpl的add方法呢?可以模仿B/S架構(gòu)的調(diào)用方式,在B服務(wù)暴露一個Restful接口,然后A服務(wù)通過調(diào)用這個Restful接口來間接調(diào)用CalculatorImpl的add方法。
這樣,已經(jīng)很接近RPC了,不過,像這種每次調(diào)用時,是不是都需要寫一串發(fā)起http請求的代碼呢?比如httpClient.sendRequest...之類的,能不能簡單一下,像本地方法調(diào)用一樣,去發(fā)起遠程調(diào)用,讓使用者感知不到遠程調(diào)用的過程。
屏蔽的工作,可以使用代理模式解決,生成一個代理對象,而這個代理對象的內(nèi)部,就是通過httpClient來實現(xiàn)RPC遠程過程調(diào)用的。
這就是很多RPC框架要解決的問題和解決的思路,比如阿里的Dubbo。
總結(jié)一下,RPC要解決的兩個問題:
1. 解決分布式系統(tǒng)中,服務(wù)之間的調(diào)用問題。
2. 遠程調(diào)用時,要能夠像本地調(diào)用一樣方便,讓調(diào)用者感知不到遠程調(diào)用的邏輯。
RPC是一種技術(shù)的概念名詞
RPC=Remote Produce Call 是一種技術(shù)的概念名詞,HTTP是一種協(xié)議,RPC可以通過 HTTP 來實現(xiàn),也可以通過Socket自己實現(xiàn)一套協(xié)議來實現(xiàn).所以題目可以換一種理解,為何 RPC 還有除 HTTP 之外的實現(xiàn)法,有何必要,畢竟除了HTTP實現(xiàn)外,私有協(xié)議不具備通用性.
RPC框架好處
http接口是在接口不多、系統(tǒng)與系統(tǒng)交互較少的情況下,解決信息孤島初期常使用的一種通信手段;
優(yōu)點就是簡單、直接、開發(fā)方便。
如果是一個大型的網(wǎng)站,內(nèi)部子系統(tǒng)較多、接口非常多的情況下,RPC框架的好處就顯示出來了:
首先就是長鏈接,不必每次通信都要像http一樣去3次握手什么的,減少了網(wǎng)絡(luò)開銷;
其次就是RPC框架一般都有注冊中心,有豐富的監(jiān)控管理;發(fā)布、下線接口、動態(tài)擴展等,對調(diào)用方來說是無感知、統(tǒng)一化的操作。
***是安全性。
rpc是一種概念,http也是rpc實現(xiàn)的一種方式。
論復(fù)雜度,dubbo/hessian用起來是超級簡單的。
至于為什么用dubbo/hessian,有幾點:
一是調(diào)用簡單,真正提供了類似于調(diào)用本地方法一樣調(diào)用接口的功能 。
二是參數(shù)返回值簡單明了 參數(shù)和返回值都是直接定義在jar包里的,不需要二次解析。
三是 輕量,沒有多余的信息。
四是便于管理,基于dubbo的注冊中心。
RPC能解耦服務(wù)
RPC:遠程過程調(diào)用。RPC的核心并不在于使用什么協(xié)議。RPC的目的是讓你在本地調(diào)用遠程的方法,而對你來說這個調(diào)用是透明的,你并不知道這個調(diào)用的方法是部署哪里。
通過RPC能解耦服務(wù),這才是使用RPC的真正目的。RPC的原理主要用到了動態(tài)代理模式,至于http協(xié)議,只是傳輸協(xié)議而已。簡單的實現(xiàn)可以參考spring remoting,復(fù)雜的實現(xiàn)可以參考dubbo。
rpc=socket + 動態(tài)代理
服務(wù)器通訊原理就是一臺socket服務(wù)器A,另一臺socket客戶端B,現(xiàn)在如果要通訊的話直接以流方式寫入或讀出。這樣能實現(xiàn)通訊,但有個問題。如何知道更多信息?
比如需要發(fā)送流大小,編碼,Ip等。這樣就有了協(xié)議,協(xié)議就是規(guī)范,就是發(fā)送的流中攜帶了很多的內(nèi)容。那回到剛剛的問題。發(fā)送的內(nèi)容就是文本類型,客戶端就得序列化,那么常用的就有json,xml之類,如果想把內(nèi)容變得更小,那就有二進制了。把文本變成二進制傳遞。
說到 rpc 與http接口,不要太復(fù)雜了。rpc 協(xié)議更簡單內(nèi)容更小,那么來說效率是要高一點
rpc 是什么?就是socket 加動態(tài)代理。
總結(jié)
學(xué)技術(shù)應(yīng)該是知其然知其所以然,我們得明白什么場景,或者什么業(yè)務(wù)需要它,它能解決其他技術(shù)不能解決或者不方便解決的問題。
RPC是一個軟件結(jié)構(gòu)概念,是構(gòu)建分布式應(yīng)用的理論基礎(chǔ)。就好比為啥你家可以用到發(fā)電廠發(fā)出來的電?是因為電是可以傳輸?shù)?。至于用銅線還是用鐵絲還是其他種類的導(dǎo)線,也就是用http還是用其他協(xié)議的問題了。這個要看什么場景,對性能要求怎么樣。
在java中的最基本的就是RMI技術(shù),它是java原生的應(yīng)用層分布式技術(shù)。我們可以肯定的是在傳輸性能方面,RMI的性能是優(yōu)于HTTP的。
那為啥很少用到這個技術(shù)?那是因為用這個有很多局限性,首先它要保證傳輸?shù)膬啥硕家胘ava實現(xiàn),且兩邊需要有相同的對象類型和代理接口,不需要容器,但是加大了編程的難度,在應(yīng)用內(nèi)部的各個子系統(tǒng)之間還是會看到他的身影,比如EJB就是基于rmi技術(shù)的。
這就與目前的bs架構(gòu)的軟件大相徑庭。用http必須要服務(wù)端位于http容器里面,這樣減少了網(wǎng)絡(luò)傳輸方面的開發(fā),只需要關(guān)注業(yè)務(wù)開發(fā)即可。所以在架構(gòu)一個軟件的時候,不能一定根據(jù)需求選定技術(shù)。