溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

RPC核心知識點有哪些

發(fā)布時間:2022-01-04 16:13:58 來源:億速云 閱讀:174 作者:iii 欄目:云計算

這篇文章主要講解了“RPC核心知識點有哪些”,文中的講解內(nèi)容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“RPC核心知識點有哪些”吧!


RPC 全稱是 Remote Procedure Call ,即遠程過程調(diào)用,其對應的是我們的本地調(diào)用。

遠程其實指的就是需要網(wǎng)絡通信,可以理解為調(diào)用遠程機器上的方法。

那可能有人說:我用 HTTP 調(diào)用不就是遠程調(diào)用了,那不也叫 RPC 了?

不是的,RPC 的目的是:讓我們調(diào)用遠程方法像調(diào)用本地方法一樣無差別。

來看下代碼就很清晰,比如本來沒有拆分服務都是本地調(diào)用的時候方法是這樣寫的:

    public String getSth(String str) {          return yesService.get(str);     }

如果 yesSerivce 被拆分出去,此時需要遠程調(diào)用了,如果用 HTTP 方式,可能就是:

    public String getSth(String str) {         RequestParam param = new RequestParam();         ......         return HttpClient.get(url, param,.....);     }

此時需要關(guān)心遠程服務的地址,還需要組裝請求等等,而如果采用 RPC 調(diào)用那就是:

    public String getSth(String str) {         // 看起來和之前調(diào)用沒差?哈哈沒唬你,         // 具體的實現(xiàn)已經(jīng)搬到另一個服務上了,這里只有接口。         // 看完下面就知道了。          return yesService.get(str);       }

所以說  RPC 其實就是用來屏蔽遠程調(diào)用網(wǎng)絡相關(guān)的細節(jié),使得遠程調(diào)用和本地調(diào)用使用一致,讓開發(fā)的效率更高。

在了解了 RPC 的作用之后,我們來看看 RPC 調(diào)用需要經(jīng)歷哪些步驟。

RPC 調(diào)用基本流程

按上面的例子來說,yesService 服務實現(xiàn)被移到了遠程服務上,本地沒有具體的實現(xiàn)只有一個接口。

那這時候我們需要調(diào)用 yesService.get(str) ,該怎么辦呢?

我們所要做的就是把傳入的參數(shù)和調(diào)用的接口全限定名通過網(wǎng)絡通信告知到遠程服務那里。

然后遠程服務接收到參數(shù)和接口全限定名就能選中具體的實現(xiàn)并進行調(diào)用。

業(yè)務處理完之后再通過網(wǎng)絡返回結(jié)果,這就搞定了!

RPC核心知識點有哪些

上面的操作這些就是由yesService.get(str) 觸發(fā)的。

不過我們知道 yesService 就是一個接口,沒有實現(xiàn)的,所以這些操作是怎么來的?

是通過動態(tài)代理來的。

RPC 會給接口生成一個代理類,所以我們調(diào)用這個接口實際調(diào)用的是動態(tài)生成的代理類,由代理類來觸發(fā)遠程調(diào)用,這樣我們調(diào)用遠程接口就無感知了。

動態(tài)代理想必大家都比較熟悉,最常見的就是 Spring 的 AOP 了,涉及的有 JDK 動態(tài)代理和 cglib。

在 Dubbo 中用的是 Javassist,至于為什么用這個其實梁飛大佬已經(jīng)寫了博客說明了。

他當時對比了 JDK 自帶的、ASM、CGLIB(基于ASM包裝)、Javassist。

經(jīng)過測試最終選用了 Javassist。

梁飛:最終決定使用JAVAASSIST的字節(jié)碼生成代理方式。雖然ASM稍快,但并沒有快一個數(shù)量級,而JAVAASSIST的字節(jié)碼生成方式比ASM方便,JAVAASSIST只需用字符串拼接出Java源碼,便可生成相應字節(jié)碼,而ASM需要手工寫字節(jié)碼。

可以看到選擇一個框架的時候性能是一方面,易用性也很關(guān)鍵。

說回 RPC 。

現(xiàn)在我們知道動態(tài)代理屏蔽了 RPC 調(diào)用的細節(jié),使得用戶無感知的調(diào)用遠程服務,那調(diào)用的細節(jié)有哪些呢?

序列化

像我們的請求參數(shù)都是對象,有時候是定義的  DTO ,有時候是 Map ,這些對象是無法直接在網(wǎng)絡中傳輸?shù)摹?/p>

你可以理解為對象是“立體”的,而網(wǎng)絡傳輸?shù)臄?shù)據(jù)是“扁平”的,最終需要轉(zhuǎn)化成“扁平”的二進制數(shù)據(jù)在網(wǎng)絡中傳輸。

RPC核心知識點有哪些

你想想,各對象分配在內(nèi)存不同位置,各種引用,這看起來是不是有種立體的感覺?

最終都是要變成一段01組成的數(shù)字傳輸給對方,這種就01組成的數(shù)字看起來是不是很“扁平”?

把對象轉(zhuǎn)化成二進制數(shù)據(jù)的過程稱為序列化,把二進制數(shù)據(jù)轉(zhuǎn)化成對象的過程稱為反序列化。

當然如何選擇序列化格式也很重要。

比如采用二進制的序列化格式數(shù)據(jù)更加緊湊,采用 JSON 等文本型序列化格式可讀性更佳,排查問題比較方便。

還有很多序列化選擇,一般需要綜合考慮通用性、性能、可讀性和兼容性。

具體本文就不分析了,之后再專門寫一篇分析各種序列化協(xié)議的。

RPC 協(xié)議

剛才也提到了只有二進制數(shù)據(jù)才能在網(wǎng)絡中傳輸,那一堆二進制在底層看來是連起來的,它可不會管你哪些數(shù)據(jù)是哪個請求的。

但接收方得知道呀,不然就不能順利的把二進制數(shù)據(jù)還原成對應的一個個請求了。

于是就需要定義一個協(xié)議,來約定一些規(guī)范,制定一些邊界使得二進制數(shù)據(jù)可以被還原。

比如下面一串數(shù)字按照不同位數(shù)來識別得到的結(jié)果是不同的。

RPC核心知識點有哪些

所以協(xié)議其實就定義了到底如何構(gòu)造和解析這些二進制數(shù)據(jù)。

我們的參數(shù)肯定比上面的復雜,因為參數(shù)值長度是不定的,而且協(xié)議常常伴隨著升級而擴展,畢竟有時候需要加一些新特性,那么協(xié)議就得變了。

一般 RPC 協(xié)議都是采用協(xié)議頭+協(xié)議體的方式。

協(xié)議頭放一些元數(shù)據(jù),包括:魔法位、協(xié)議的版本、消息的類型、序列化方式、整體長度、頭長度、擴展位等。

協(xié)議體就是放請求的數(shù)據(jù)了。

通過魔法位可以得知這是不是咱們約定的協(xié)議,比如魔法位固定叫 233 ,一看我們就知道這是 233 協(xié)議。

然后協(xié)議的版本是為了之后協(xié)議的升級。

從整體長度和頭長度我們就能知道這個請求到底有多少位,前面多少位是頭,剩下的都是協(xié)議體,這樣就能識別出來,擴展位就是留著日后擴展備用。

貼一下 Dubbo 協(xié)議:

RPC核心知識點有哪些

可以看到有 Magic 位,請求  ID, 數(shù)據(jù)長度等等。

網(wǎng)絡傳輸

組裝好數(shù)據(jù)就等著發(fā)送了,這時候就涉及網(wǎng)絡傳輸了。

網(wǎng)絡通信那就離不開網(wǎng)絡 IO 模型了。

RPC核心知識點有哪些

網(wǎng)絡 IO 分為這四種模型,具體以后單獨寫文章分析,這篇就不展開了。

一般而言我們用的都是 IO 多路復用,因為大部分 RPC 調(diào)用場景都是高并發(fā)調(diào)用,IO 復用可以利用較少的線程 hold 住很多請求。

一般 RPC 框架會使用已經(jīng)造好的輪子來作為底層通信框架。

例如 Java 語言的都會用 Netty ,人家已經(jīng)封裝的很好了,也做了很多優(yōu)化,拿來即用,便捷高效。

小結(jié)

RPC 通信的基礎(chǔ)流程已經(jīng)講完了,看下圖:

RPC核心知識點有哪些

響應返回就沒畫了,反正就是倒著來。

我再用一段話來總結(jié)一下:

服務調(diào)用方,面向接口編程,利用動態(tài)代理屏蔽底層調(diào)用細節(jié)將請求參數(shù)、接口等數(shù)據(jù)組合起來并通過序列化轉(zhuǎn)化為二進制數(shù)據(jù),再通過 RPC 協(xié)議的封裝利用網(wǎng)絡傳輸?shù)椒仗峁┓健?/p>

服務提供方根據(jù)約定的協(xié)議解析出請求數(shù)據(jù),然后反序列化得到參數(shù),找到具體調(diào)用的接口,然后執(zhí)行具體實現(xiàn),再返回結(jié)果。

這里面還有很多細節(jié)。

比如請求都是異步的,所以每個請求會有唯一 ID,返回結(jié)果會帶上對應的 ID, 這樣調(diào)用方就能通過 ID 找到對應的請求塞入相應的結(jié)果。

有人會問為什么要異步,那是為了提高吞吐。

當然還有很多細節(jié),會在之后剖析 Dubbo 的時候提到,結(jié)合實際中間件體會才會更深。

真正工業(yè)級別的 RPC

以上提到的只是 RPC 的基礎(chǔ)流程,這對于工業(yè)級別的使用是遠遠不夠的。

生產(chǎn)環(huán)境中的服務提供者都是集群部署的,所以有多個提供者,而且還會隨著大促等流量情況動態(tài)增減機器。

因此需要注冊中心,作為服務的發(fā)現(xiàn)。

調(diào)用者可以通過注冊中心得知服務提供者們的 IP 地址等元信息,進行調(diào)用。

調(diào)用者也能通過注冊中心得知服務提供者下線。

還需要有路由分組策略,調(diào)用者根據(jù)下發(fā)的路由信息選擇對應的服務提供者,能實現(xiàn)分組調(diào)用、灰度發(fā)布、流量隔離等功能。

還需要有負載均衡策略,一般經(jīng)過路由過濾之后還是有多個服務提供者可以選擇,通過負載均衡策略來達到流量均衡。

當然還需要有異常重試,畢竟網(wǎng)絡是不穩(wěn)定的,而且有時候某個服務提供者也可能出點問題,所以一次調(diào)用出錯進行重試,較少業(yè)務的損耗。

還需要限流熔斷,限流是因為服務提供者不知道會接入多少調(diào)用者,也不清楚每個調(diào)用者的調(diào)用量,所以需要衡量一下自身服務的承受值來進行限流,防止服務崩潰。

而熔斷是為了防止下游服務故障導致自身服務調(diào)用超時阻塞堆積而崩潰,特別是調(diào)用鏈很長的那種,影響很大。

比如A=>B=>C=>D=>E,然后 E 出了故障,你看ABCD四個服務就傻等著,慢慢的資源就占滿了就崩了,全崩。

RPC核心知識點有哪些

大致就是以上提到的幾點,不過還能細化,比如負載均衡的各種策略、限流到底是限制總流量還是根據(jù)每個調(diào)用者指定限流量,還是上自適應限流等等。

感謝各位的閱讀,以上就是“RPC核心知識點有哪些”的內(nèi)容了,經(jīng)過本文的學習后,相信大家對RPC核心知識點有哪些這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關(guān)知識點的文章,歡迎關(guān)注!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

rpc
AI