RPC核心原理

大家好,我是易安,今天我們一起來研究下RPC的核心原理。

什么是RPC?

RPC的全稱是Remote Procedure Call,即遠(yuǎn)程過程調(diào)用。簡單解讀字面上的意思,遠(yuǎn)程肯定是指要跨機器而非本機,所以需要用到網(wǎng)絡(luò)編程才能實現(xiàn),但是不是只要通過網(wǎng)絡(luò)通信訪問到另一臺機器的應(yīng)用程序,就可以稱之為RPC調(diào)用了?顯然并不夠。

我理解的RPC是幫助我們屏蔽網(wǎng)絡(luò)編程細(xì)節(jié),實現(xiàn)調(diào)用遠(yuǎn)程方法就跟調(diào)用本地(同一個項目中的方法)一樣的體驗,我們不需要因為這個方法是遠(yuǎn)程調(diào)用就需要編寫很多與業(yè)務(wù)無關(guān)的代碼。

這就好比建在小河上的橋一樣連接著河的兩岸,如果沒有小橋,我們需要通過劃船、繞道等其他方式才能到達對面,但是有了小橋之后,我們就能像在路面上一樣行走到達對面,并且跟在路面上行走的體驗沒有區(qū)別。所以 我認(rèn)為,RPC的作用就是體現(xiàn)在這樣兩個方面:

  • 屏蔽遠(yuǎn)程調(diào)用跟本地調(diào)用的區(qū)別,讓我們感覺就是調(diào)用項目內(nèi)的方法;
  • 隱藏底層網(wǎng)絡(luò)通信的復(fù)雜性,讓我們更專注于業(yè)務(wù)邏輯。

RPC通信流程

理解了什么是RPC,接下來我們講下RPC框架的通信流程,方便我們進一步理解RPC。

如前面所講,RPC能幫助我們的應(yīng)用透明地完成遠(yuǎn)程調(diào)用,發(fā)起調(diào)用請求的那一方叫做調(diào)用方,被調(diào)用的一方叫做服務(wù)提供方。為了實現(xiàn)這個目標(biāo),我們就需要在RPC框架里面對整個通信細(xì)節(jié)進行封裝, 那一個完整的RPC會涉及到哪些步驟呢?

我們已經(jīng)知道RPC是一個遠(yuǎn)程調(diào)用,那肯定就需要通過網(wǎng)絡(luò)來傳輸數(shù)據(jù),并且RPC常用于業(yè)務(wù)系統(tǒng)之間的數(shù)據(jù)交互,需要保證其可靠性,所以RPC一般默認(rèn)采用TCP來傳輸。我們常用的HTTP協(xié)議也是建立在TCP之上的。

網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)必須是二進制數(shù)據(jù),但調(diào)用方請求的出入?yún)?shù)都是對象。對象是肯定沒法直接在網(wǎng)絡(luò)中傳輸?shù)?,需要提前把它轉(zhuǎn)成可傳輸?shù)亩M制,并且要求轉(zhuǎn)換算法是可逆的,這個過程我們一般叫做“序列化”。

調(diào)用方持續(xù)地把請求參數(shù)序列化成二進制后,經(jīng)過TCP傳輸給了服務(wù)提供方。服務(wù)提供方從TCP通道里面收到二進制數(shù)據(jù),那如何知道一個請求的數(shù)據(jù)到哪里結(jié)束,是一個什么類型的請求呢?

在這里我們可以想想高速公路,它上面有很多出口,為了讓司機清楚地知道從哪里出去,管理部門會在路上建立很多指示牌,并在指示牌上標(biāo)明下一個出口是哪里、還有多遠(yuǎn)。那回到數(shù)據(jù)包識別這個場景,我們是不是也可以建立一些“指示牌”,并在上面標(biāo)明數(shù)據(jù)包的類型和長度,這樣就可以正確的解析數(shù)據(jù)了。確實可以,并且我們把數(shù)據(jù)格式的約定內(nèi)容叫做“協(xié)議”。大多數(shù)的協(xié)議會分成兩部分,分別是數(shù)據(jù)頭和消息體。數(shù)據(jù)頭一般用于身份識別,包括協(xié)議標(biāo)識、數(shù)據(jù)大小、請求類型、序列化類型等信息;消息體主要是請求的業(yè)務(wù)參數(shù)信息和擴展屬性等。

根據(jù)協(xié)議格式,服務(wù)提供方就可以正確地從二進制數(shù)據(jù)中分割出不同的請求來,同時根據(jù)請求類型和序列化類型,把二進制的消息體逆向還原成請求對象。這個過程叫作“反序列化”。

服務(wù)提供方再根據(jù)反序列化出來的請求對象找到對應(yīng)的實現(xiàn)類,完成真正的方法調(diào)用,然后把執(zhí)行結(jié)果序列化后,回寫到對應(yīng)的TCP通道里面。調(diào)用方獲取到應(yīng)答的數(shù)據(jù)包后,再反序列化成應(yīng)答對象,這樣調(diào)用方就完成了一次RPC調(diào)用。

那上述幾個流程就組成了一個完整的RPC嗎?

似乎,還缺點東西。因為對于研發(fā)人員來說,這樣做要掌握太多的RPC底層細(xì)節(jié),需要手動寫代碼去構(gòu)造請求、調(diào)用序列化,并進行網(wǎng)絡(luò)調(diào)用,整個API非常不友好。

那我們有什么辦法來簡化API,屏蔽掉RPC細(xì)節(jié),讓使用方只需要關(guān)注業(yè)務(wù)接口,像調(diào)用本地一樣來調(diào)用遠(yuǎn)程呢?

如果你了解Spring,一定對其AOP技術(shù)很佩服,其核心是采用動態(tài)代理的技術(shù),通過字節(jié)碼增強對方法進行攔截增強,以便于增加需要的額外處理邏輯。其實這個技術(shù)也可以應(yīng)用到RPC場景來解決我們剛才面臨的問題。

由服務(wù)提供者給出業(yè)務(wù)接口聲明,在調(diào)用方的程序里面,RPC框架根據(jù)調(diào)用的服務(wù)接口提前生成動態(tài)代理實現(xiàn)類,并通過依賴注入等技術(shù)注入到聲明了該接口的相關(guān)業(yè)務(wù)邏輯里面。該代理實現(xiàn)類會攔截所有的方法調(diào)用,在提供的方法處理邏輯里面完成一整套的遠(yuǎn)程調(diào)用,并把遠(yuǎn)程調(diào)用結(jié)果返回給調(diào)用方,這樣調(diào)用方在調(diào)用遠(yuǎn)程方法的時候就獲得了像調(diào)用本地接口一樣的體驗。

到這里,一個簡單版本的RPC框架就實現(xiàn)了:

RPC在架構(gòu)中的位置

圍繞RPC我們講了這么多,那RPC在架構(gòu)中究竟處于什么位置呢?

如剛才所講,RPC是解決應(yīng)用間通信的一種方式,而無論是在一個大型的分布式應(yīng)用系統(tǒng)還是中小型系統(tǒng)中,應(yīng)用架構(gòu)最終都會從“單體”演進成“微服務(wù)化”,整個應(yīng)用系統(tǒng)會被拆分為多個不同功能的應(yīng)用,并將它們部署在不同的服務(wù)器中,而應(yīng)用之間會通過RPC進行通信,可以說RPC對應(yīng)的是整個分布式應(yīng)用系統(tǒng),就像是“經(jīng)絡(luò)”一樣的存在。

那么如果沒有RPC,我們現(xiàn)實中的開發(fā)過程是怎樣的一個體驗?zāi)兀?/p>

所有的功能代碼都會被我們堆砌在一個大項目中,開發(fā)過程中你可能要改一行代碼,但改完后編譯會花掉你2分鐘,編譯完想運行起來驗證下結(jié)果可能要5分鐘,是不是很酸爽?更難受的是在人數(shù)比較多的團隊里面,多人協(xié)同開發(fā)的時候,如果團隊其他人把接口定義改了,你連編譯通過的機會都沒有,系統(tǒng)直接報錯,從而導(dǎo)致整個團隊的開發(fā)效率都會非常低下。而且當(dāng)我們準(zhǔn)備要上線發(fā)版本的時候,QA也很難評估這次的測試范圍,為了保險起見我們只能把所有的功能進行回歸測試,這樣會導(dǎo)致我們上線新功能的整體周期都特別長。

無論你是研發(fā)還是架構(gòu)師,我相信這種系統(tǒng)架構(gòu)我們肯定都不能接受,那怎么才能解決這個問題呢?

我們首先都會想到可以采用“分而治之”的思想來進行拆分,但是拆分完的系統(tǒng)怎么保持跟未拆分前的調(diào)用方式一樣呢?我們總不能因為架構(gòu)升級,就把所有的代碼都推倒重寫一遍吧。

RPC框架能夠幫助我們解決系統(tǒng)拆分后的通信問題,并且能讓我們像調(diào)用本地一樣去調(diào)用遠(yuǎn)程方法。 利用RPC我們不僅可以很方便地將應(yīng)用架構(gòu)從“單體”演進成“微服務(wù)化”,而且還能解決實際開發(fā)過程中的效率低下、系統(tǒng)耦合等問題,這樣可以使得我們的系統(tǒng)架構(gòu)整體清晰、健壯,應(yīng)用可運維度增強。

當(dāng)然RPC不僅可以用來解決通信問題,它還被用在了很多其他場景,比如:發(fā)MQ、分布式緩存、數(shù)據(jù)庫等。比如下面這個應(yīng)用示例:

這個應(yīng)用中,使用了MQ來處理異步流程、Redis緩存熱點數(shù)據(jù)、MySQL持久化數(shù)據(jù),還有就是在系統(tǒng)中調(diào)用另外一個業(yè)務(wù)系統(tǒng)的接口,對我的應(yīng)用來說這些都是屬于RPC調(diào)用,而MQ、MySQL持久化的數(shù)據(jù)也會存在于一個分布式文件系統(tǒng)中,他們之間的調(diào)用也是需要用RPC來完成數(shù)據(jù)交互的。

由此可見,RPC確實是我們?nèi)粘i_發(fā)中經(jīng)常接觸的東西,只是被包裝成了各種框架,導(dǎo)致我們很少意識到這就是RPC,讓RPC變成了我們最“熟悉的陌生人”。現(xiàn)在,回過頭想想,我說RPC是整個應(yīng)用系統(tǒng)的“經(jīng)絡(luò)”,這不為過吧?我們真的很有必要學(xué)好RPC,不僅因為RPC是構(gòu)建復(fù)雜系統(tǒng)的基石,還是提升自身認(rèn)知的利器。

總結(jié)

本文主要講了下RPC的原理,RPC就是提供一種透明調(diào)用機制,讓使用者不必顯式地區(qū)分本地調(diào)用和遠(yuǎn)程調(diào)用。RPC雖然可以幫助開發(fā)者屏蔽遠(yuǎn)程調(diào)用跟本地調(diào)用的區(qū)別,但畢竟涉及到遠(yuǎn)程網(wǎng)絡(luò)通信,所以這里還是有很多使用上的區(qū)別,比如:

  • 調(diào)用過程中超時了怎么處理業(yè)務(wù)?
  • 什么場景下最適合使用RPC?
  • 什么時候才需要考慮開啟壓縮?

無論你是一個初級開發(fā)者還是高級開發(fā)者,RPC都應(yīng)該是你日常開發(fā)過程中繞不開的一個話題,所以作為軟件開發(fā)者的我們,真的很有必要詳細(xì)地了解RPC實現(xiàn)細(xì)節(jié)。只有這樣,才能幫助我們更好地在日常工作中使用RPC。

本文由mdnice多平臺發(fā)布

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容