成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

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

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

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

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

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

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

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

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

圖片圖片

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

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

圖片圖片

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

圖片圖片

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

圖片圖片

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

圖片圖片

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

圖片圖片

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

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

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

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

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

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

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

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

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

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

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

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

好,下面我們就具體來(lái)看看。

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

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

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

序列化

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

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

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

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

圖片

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

傳輸協(xié)議

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

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

圖片圖片

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

這也是大部分 RPC 框架內(nèi)部所采用的實(shí)現(xiàn)方式,這樣做的主要目的是對(duì)公有協(xié)議進(jìn)行精簡(jiǎn),從而提升性能。另外,出于擴(kuò)展性的考慮,具備高度定制化的私有協(xié)議也比公共協(xié)議更加容易實(shí)現(xiàn)擴(kuò)展。這方面的典型示例還是 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)模式和請(qǐng)求應(yīng)答(Request-Response)模式,前者體現(xiàn)為異步操作,后者一般執(zhí)行同步操作。

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

圖片圖片

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

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

圖片圖片

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

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

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

總結(jié)

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

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

2024-01-03 09:03:40

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

2025-01-07 09:07:36

接口屬性路徑

2023-08-10 08:28:46

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

2023-08-04 08:20:56

DockerfileDocker工具

2023-06-30 08:18:51

敏捷開(kāi)發(fā)模式

2022-05-24 08:21:16

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

2023-09-10 21:42:31

2022-10-08 00:00:05

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

2022-06-15 08:00:50

磁盤(pán)RedisRocketMQ

2023-04-26 07:30:00

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

2024-02-20 21:34:16

循環(huán)GolangGo

2021-08-27 07:06:10

IOJava抽象

2023-11-07 08:13:53

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

2023-08-02 08:35:54

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

2022-12-06 08:12:11

Java關(guān)鍵字

2022-09-08 08:50:17

SSDOracleCPU

2024-09-09 08:53:56

2024-06-14 09:32:12

2023-03-26 23:47:32

Go內(nèi)存模型

2024-07-26 09:47:28

點(diǎn)贊
收藏

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

主站蜘蛛池模板: 羞羞网站在线免费观看 | 99精品免费| www.免费看片.com | 欧美黑人一区 | 国产精品三级久久久久久电影 | 国产成人一区二区 | 成人免费视频 | 久久精品无码一区二区三区 | 欧美一区 | 精品福利一区二区三区 | 99精品久久 | 成人亚洲精品久久久久软件 | 91精品久久久久久久久久入口 | 91中文字幕在线观看 | 久久久精品久久久 | 狠狠色综合网站久久久久久久 | 久久男人天堂 | 欧美国产一区二区三区 | 国产一区免费视频 | 国产在线高清 | 亚洲精品一区中文字幕乱码 | 国产成人精品综合 | 91免费观看视频 | 国产精品天堂 | 国产一区二区在线免费 | 天堂色 | 亚洲激情视频在线 | 欧美精品一区二区三区四区五区 | 三级免费 | 欧美精品一| 性一交一乱一伦视频免费观看 | 国产欧美精品一区二区色综合朱莉 | 91视频在线看 | 成人婷婷| 成人激情视频网 | 黄色91在线 | 久久91av | 国产精品美女久久久久aⅴ国产馆 | 一区二区三区日韩 | 国产成人99久久亚洲综合精品 | 中文字幕亚洲区 |