自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

我們一起聊聊 RPC 的底層原理

開發(fā) 前端
如果想要實現(xiàn)服務(wù)提供者和消費者之間的有效交互,那么兩者之間就需要確立與網(wǎng)絡(luò)通信相關(guān)的網(wǎng)絡(luò)協(xié)議以及通信通道。同時,服務(wù)的提供者需要把自己的服務(wù)調(diào)用入口暴露出來,并時刻準(zhǔn)備接收來自消費者的請求。

當(dāng)你在構(gòu)建一個分布式系統(tǒng)時,勢必需要考慮的一個問題是:如何實現(xiàn)服務(wù)與服務(wù)之間的調(diào)用?當(dāng)然,你可以使用 Dubbo 或 Spring Cloud 等分布式服務(wù)框架來封裝技術(shù)實現(xiàn)的復(fù)雜性,以此完成這個目標(biāo)。不過,假如現(xiàn)在沒有這些框架,需要你自己來實現(xiàn)遠(yuǎn)程調(diào)用,你會怎么做呢?

很多人會選擇實現(xiàn)一套 RPC 框架來調(diào)用遠(yuǎn)程服務(wù)。

那么你了解 RPC 架構(gòu)的基本結(jié)構(gòu)嗎?如果你想要自己實現(xiàn) RPC 框架來完成遠(yuǎn)程調(diào)用,又該構(gòu)建怎么樣的技術(shù)體系呢?接下來,我就給你具體介紹一下。

RPC 架構(gòu)的基本結(jié)構(gòu)

想要構(gòu)建一套完整的 RPC 架構(gòu),就需要明確該架構(gòu)所具備的基本結(jié)構(gòu),而 RPC 架構(gòu)的基本結(jié)構(gòu)中又存在很多組件。因此接下來,我就通過 RPC 基本結(jié)構(gòu)演進的過程,來給你一一講解下。

首先,我們通常把發(fā)生調(diào)用關(guān)系的兩個服務(wù)分別稱為服務(wù)的提供者(Provider)和消費者(Consumer)。所以,簡單來說,RPC 就是服務(wù)的消費者向提供者發(fā)起遠(yuǎn)程調(diào)用并獲取結(jié)果的過程,這是 RPC 最簡單的一種表現(xiàn)形式。

圖片圖片

如果想要實現(xiàn)服務(wù)提供者和消費者之間的有效交互,那么兩者之間就需要確立與網(wǎng)絡(luò)通信相關(guān)的網(wǎng)絡(luò)協(xié)議以及通信通道。同時,服務(wù)的提供者需要把自己的服務(wù)調(diào)用入口暴露出來,并時刻準(zhǔn)備接收來自消費者的請求。

這里,我們把通信通道和網(wǎng)絡(luò)協(xié)議分別命名為 RpcChannel 和 RpcProtocol,而把服務(wù)提供者接收請求的組件稱為 RpcAcceptor,把消費者發(fā)起請求的組件稱為 RpcConnector。這樣,RPC 架構(gòu)就演變成了這個樣子:

圖片圖片

然后,對于服務(wù)提供者和消費者而言,為了雙方能夠正常識別所發(fā)送的請求和所接收到的響應(yīng)結(jié)果,需要定義統(tǒng)一的契約。我們把這種契約稱為遠(yuǎn)程 API(Remote API),以便與本地 API 加以區(qū)別。如此一來,基于同一套遠(yuǎn)程 API 的定義,RPC 架構(gòu)就具備了根據(jù)業(yè)務(wù)來定義通信契約的能力。

圖片圖片

類似地,為了更好地區(qū)分 RPC 架構(gòu)中的角色,我們把真正提供業(yè)務(wù)服務(wù)的組件稱為 RpcServer,而把發(fā)起真實客戶端請求的組件稱為 RpcClient。這樣,RpcServer 負(fù)責(zé)實現(xiàn)遠(yuǎn)程 API,而 RpcClient 負(fù)責(zé)調(diào)用遠(yuǎn)程 API。

圖片圖片

當(dāng)然,對于遠(yuǎn)程 API 而言,服務(wù)提供者和消費者的處理方式顯然是不一樣的。提供者需要根據(jù)消費者的請求來調(diào)用 RpcServer 的具體實現(xiàn)并返回結(jié)果,這部分的工作由 RpcInvoker 來執(zhí)行,而消費者通過 RpcCaller 組件對請求進行編碼之后,發(fā)送給服務(wù)方并等待結(jié)果。

圖片圖片

最后,為了降低開發(fā)人員的開發(fā)難度,讓遠(yuǎn)程調(diào)用的執(zhí)行過程看上去就像在執(zhí)行本地方法一樣,在主流的 RPC 實現(xiàn)機制中,通常都會在客戶端添加代理機制,以此提供遠(yuǎn)程服務(wù)本地化訪問的入口,我們把這個代理組件稱為 RpcProxy。另外,在服務(wù)器端,為了更好地控制業(yè)務(wù)方法執(zhí)行過程,通常也會引入具備線程管理、超時控制等機制的 RpcProcessor 組件。

圖片圖片

以上就是整個 RPC 架構(gòu)的演進過程了。從中你可以發(fā)現(xiàn),RPC 架構(gòu)中的客戶端組件和服務(wù)器端組件形成了一種對稱結(jié)構(gòu),它們各司其職,但又共同構(gòu)成一個整體。為了幫你加深理解,這里我再總結(jié)下前面提到的各個組件。

客戶端組件與職責(zé)包括:

  • RpcClient,負(fù)責(zé)調(diào)用遠(yuǎn)程 API,這個過程會依賴于 RpcProxy 提供的代理實現(xiàn)
  • RpcProxy,遠(yuǎn)程 API 的代理實現(xiàn),提供遠(yuǎn)程服務(wù)本地化訪問的入口
  • RpcCaller,負(fù)責(zé)編碼和發(fā)送調(diào)用請求到服務(wù)方并等待結(jié)果
  • RpcConnector,負(fù)責(zé)與服務(wù)端建立通信通道并發(fā)送請求到服務(wù)端

服務(wù)端組件與職責(zé)包括:

  • RpcServer,負(fù)責(zé)實現(xiàn)遠(yuǎn)程 API
  • RpcInvoker,負(fù)責(zé)調(diào)用服務(wù)端的具體實現(xiàn)并返回結(jié)果
  • RpcProcessor,負(fù)責(zé)對請求進行處理,高效控制調(diào)用過程
  • RpcAcceptor,負(fù)責(zé)接收客戶方請求并返回請求結(jié)果

而客戶端和服務(wù)器端所共有的組件包括:

  • RpcProtocol,負(fù)責(zé)網(wǎng)絡(luò)傳輸協(xié)議的編碼和解碼
  • RpcChannel,負(fù)責(zé)建立和維護網(wǎng)絡(luò)數(shù)據(jù)傳輸通道

這樣,我們對一個典型 RPC 架構(gòu)中的基本結(jié)構(gòu)和組件就有了完整的了解。那么,如果我們想要實現(xiàn)這個架構(gòu),需要構(gòu)建怎樣的技術(shù)體系呢?

RPC 架構(gòu)的技術(shù)體系

我們都知道,架構(gòu)是一種設(shè)計上的思想和方法,明白了它的基本結(jié)構(gòu)和組成部分之后,我們就可以進一步梳理想要實現(xiàn) RPC 架構(gòu)的技術(shù)體系,包括網(wǎng)絡(luò)通信、序列化、傳輸協(xié)議和遠(yuǎn)程調(diào)用。

網(wǎng)絡(luò)通信

我們先來看網(wǎng)絡(luò)通信。網(wǎng)絡(luò)通信的涉及面很廣,對于 RPC 架構(gòu)而言,一方面我們會重點關(guān)注性能,所以勢必要考慮基于 TCP 等特定協(xié)議的網(wǎng)絡(luò)連接方式和 IO 模型;另一方面,我們也需要考慮可靠性,因為這樣才能確保遠(yuǎn)程調(diào)用過程的穩(wěn)定。

好,下面我們就具體來看看。

首先是性能問題。一般來說,基于 TCP 協(xié)議的網(wǎng)絡(luò)連接有兩種基本方式:長連接和短連接。長連接和短連接的本質(zhì)區(qū)別是連接的創(chuàng)建和關(guān)閉策略,長連接可以復(fù)用現(xiàn)有連接,而短連接則能夠更快地釋放資源。這兩者本身各有利弊,而在 RPC 框架的實現(xiàn)過程中,考慮到性能和服務(wù)治理等因素,我們通常是使用長連接進行通信,典型的實現(xiàn)框架就是 Dubbo。

而對于 IO 模型,最簡單、最基礎(chǔ)的網(wǎng)絡(luò) IO 模型就是阻塞式 IO,即 BIO(Blocking IO)。BIO 要求客戶端請求數(shù)與服務(wù)端線程數(shù)一一對應(yīng),但是顯然,由于線程的創(chuàng)建需要消耗系統(tǒng)資源,在分布式系統(tǒng)中,服務(wù)端可以創(chuàng)建的線程數(shù)將會成為系統(tǒng)的瓶頸。因此,在 RPC 架構(gòu)中,我們通常都會使用非阻塞 IO,即 NIO(Non-blocking IO)技術(shù)來提供性能?;?NIO 模式下的多路復(fù)用機制,創(chuàng)建少數(shù)的線程就能對大量請求進行高效的響應(yīng)。

然后是針對可靠性問題,由于存在網(wǎng)絡(luò)閃斷、超時等與網(wǎng)絡(luò)狀態(tài)相關(guān)的不穩(wěn)定性因素,以及業(yè)務(wù)系統(tǒng)本身的故障,網(wǎng)絡(luò)之間的通信就必須在發(fā)生上述問題時能夠快速感知并修復(fù)。常見的網(wǎng)絡(luò)通信保障手段,包括鏈路有效性檢測及斷線之后的重連處理等。這些機制都比較常見,也不是我們討論的重點,這里就不做具體展開了。

序列化

而如果我們想要在網(wǎng)絡(luò)上傳輸數(shù)據(jù),就需要用到數(shù)據(jù)序列化技術(shù)了。

目前業(yè)界成熟的序列化工具已經(jīng)有很多,常見的 XML 和 JSON 就是文本類序列化方式的代表,它們可以讓數(shù)據(jù)以開發(fā)人員可讀的方式進行傳輸。還有一種基于二進制實現(xiàn)的方案,包括 Google 的 Protocol Buffer 和 Facebook 的 Thrift。

那么,我們在選擇序列化工具時,應(yīng)該考慮什么呢?一個關(guān)鍵指標(biāo)就是性能。

性能指標(biāo)主要包括空間復(fù)雜度、時間復(fù)雜度以及 CPU/內(nèi)存資源占用等。我在下表列舉了目前主流的一些序列化技術(shù),供你參考:

圖片

可以看到,在時間維度上,Alibaba 的 fastjson 具有一定優(yōu)勢;而從空間維度上看,相較其他技術(shù),你可以優(yōu)先選擇 Protocol Buffer。

傳輸協(xié)議

我們知道,但凡涉及通過網(wǎng)絡(luò)來傳輸數(shù)據(jù),就一定要采用某種傳輸協(xié)議。在 ISO/OSI 的 7 層網(wǎng)絡(luò)模型中,RPC 架構(gòu)的設(shè)計和實現(xiàn)通常會涉及傳輸層及以上各個層次的相關(guān)協(xié)議,我們所熟悉的 TCP 協(xié)議就屬于傳輸層,而 HTTP 協(xié)議則位于應(yīng)用層。

無論是采用 7 層網(wǎng)絡(luò)模型中的哪一層,在網(wǎng)絡(luò)請求過程中,數(shù)據(jù)都是以消息的形式進行傳遞。而消息的組成是有一定結(jié)構(gòu)的,消息頭和消息體構(gòu)成了所傳輸消息的主體,其中消息體表示需要傳輸?shù)臉I(yè)務(wù)數(shù)據(jù),而消息頭用于進行傳輸控制。

圖片圖片

可以看到,每個層次都從上層取得數(shù)據(jù),加上消息頭信息形成新的消息體,并將新的消息傳遞給下一層次。通過對消息頭和消息體進行擴展,我們就可以實現(xiàn)私有化的傳輸協(xié)議。

這也是大部分 RPC 框架內(nèi)部所采用的實現(xiàn)方式,這樣做的主要目的是對公有協(xié)議進行精簡,從而提升性能。另外,出于擴展性的考慮,具備高度定制化的私有協(xié)議也比公共協(xié)議更加容易實現(xiàn)擴展。這方面的典型示例還是 Dubbo 框架,它提供了完全自定義的 Dubbo 協(xié)議。

遠(yuǎn)程調(diào)用

明確了網(wǎng)絡(luò)通信的基本方式、序列化手段以及所采用的傳輸協(xié)議之后,我們就可以發(fā)起真正的遠(yuǎn)程調(diào)用了。RPC 本質(zhì)也是一種服務(wù)調(diào)用,而服務(wù)調(diào)用存在兩種基本方式,即單向(One Way)模式和請求應(yīng)答(Request-Response)模式,前者體現(xiàn)為異步操作,后者一般執(zhí)行同步操作。

首先我們要知道,同步調(diào)用會造成業(yè)務(wù)線程阻塞,但開發(fā)和管理會相對簡單。這是為什么呢?我們先來看一下同步調(diào)用的時序圖:

圖片圖片

從中可以看到,服務(wù)線程發(fā)送請求到 IO 線程之后,就一直處于等待階段,直到 IO 線程完成與網(wǎng)絡(luò)的讀寫操作之后,才會被主動喚醒。

而使用異步調(diào)用的目的就在于獲取高性能。在實現(xiàn)異步調(diào)用過程中,我們通常都會使用到 Java 中所提供的 Future 機制。Future 調(diào)用可以進一步細(xì)分成兩種模式,F(xiàn)uture-Get 模式和 Future-Listener 模式。Future-Get 模式參考下圖:

圖片圖片

可以看到在這種模式下,服務(wù)線程通過主動 get 結(jié)果的方式獲取 Future 結(jié)果,而這個 get 過程是串行的,會造成執(zhí)行 get 方法的線程形成阻塞。

Future-Listener 模式則不同,在 Future-Listener 模式中需要創(chuàng)建 Listener,當(dāng) Future 結(jié)果生成時會喚醒注冊到該 Future 上的 Listener 對象,從而形成異步回調(diào)機制。

除了同步和異步調(diào)用之外,還存在并行(Parallel)調(diào)用和泛化(Generic)調(diào)用等調(diào)用方法,雖然也有其特定的應(yīng)用場景,但對于 RPC 架構(gòu)而言并不是主流的調(diào)用方式,這里就不具體展開了。

總結(jié)

可以說,RPC 是分布式系統(tǒng)中一項基礎(chǔ)設(shè)施類的技術(shù)體系,但凡涉及服務(wù)與服務(wù)之間的交互就需要使用到 RPC 架構(gòu)。當(dāng)你在使用一個分布式框架時,可以嘗試用今天介紹的 RPC 架構(gòu)的基本結(jié)構(gòu)和技術(shù)體系進行分析,從而加深對這項技術(shù)體系的理解。

責(zé)任編輯:武曉燕 來源: 程序員技術(shù)充電站
相關(guān)推薦

2024-01-03 09:03:40

MySQL索引數(shù)據(jù)庫

2025-01-07 09:07:36

接口屬性路徑

2022-06-15 08:00:50

磁盤RedisRocketMQ

2022-10-08 00:00:05

SQL機制結(jié)構(gòu)

2023-04-26 07:30:00

promptUI非結(jié)構(gòu)化

2023-08-04 08:20:56

DockerfileDocker工具

2022-05-24 08:21:16

數(shù)據(jù)安全API

2023-08-10 08:28:46

網(wǎng)絡(luò)編程通信

2023-09-10 21:42:31

2023-06-30 08:18:51

敏捷開發(fā)模式

2021-08-27 07:06:10

IOJava抽象

2024-02-20 21:34:16

循環(huán)GolangGo

2023-11-07 08:13:53

分布式網(wǎng)絡(luò)

2023-06-28 07:49:02

2022-09-08 08:50:17

SSDOracleCPU

2024-06-14 09:32:12

2022-12-06 08:12:11

Java關(guān)鍵字

2023-08-02 08:35:54

文件操作數(shù)據(jù)源

2024-09-09 08:53:56

2021-07-31 11:40:55

Openresty開源
點贊
收藏

51CTO技術(shù)棧公眾號