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