新聞中心
這篇文章我們來聊一聊RPC框架,為什么要聊RPC呢 ?

網(wǎng)站設(shè)計制作、網(wǎng)站制作介紹好的網(wǎng)站是理念、設(shè)計和技術(shù)的結(jié)合。成都創(chuàng)新互聯(lián)擁有的網(wǎng)站設(shè)計理念、多方位的設(shè)計風(fēng)格、經(jīng)驗豐富的設(shè)計團隊。提供PC端+手機端網(wǎng)站建設(shè),用營銷思維進行網(wǎng)站設(shè)計、采用先進技術(shù)開源代碼、注重用戶體驗與SEO基礎(chǔ),將技術(shù)與創(chuàng)意整合到網(wǎng)站之中,以契合客戶的方式做到創(chuàng)意性的視覺化效果。
首先從個人成長角度,如果一個新時代碼農(nóng)能清楚的了解RPC框架所具備的要素,掌握RPC框架中涉及的服務(wù)注冊發(fā)現(xiàn)、負載均衡、序列化協(xié)議、RPC通信協(xié)議、Socket通信、異步調(diào)用、熔斷降級等技術(shù),可以全方位的提升基本素質(zhì)。
其次,目前市面上也有非常多優(yōu)秀的框架,GitHub上也有相關(guān)源碼,但好記性不如爛筆頭,只有自己真正了解并且動手去嘗試寫一個RPC框架,才是我們?nèi)フ莆者@門技術(shù)的最優(yōu)路徑。
一、介紹
研究一個概念或者框架,帶著三個W去考慮,可能會對他有更加深刻的了解:
1)What,什么是RPC框架,RPC是 Remote Procedure Call 的簡稱,遠程過程調(diào)用,那么什么叫遠程過程調(diào)用呢,你可以理解為我們調(diào)用外部(遠程)服務(wù)就像調(diào)用自己本地方法一樣。
2)Where,RPC框架用在什么地方,在分布式系統(tǒng)和微服務(wù)盛行的今天,各業(yè)務(wù)系統(tǒng)會被獨立拆分出來成為一個個獨立的web應(yīng)用,應(yīng)用之間的交互和數(shù)據(jù)傳輸就成了必不可少的一環(huán),RPC就是為了實現(xiàn)獨立服務(wù)之間遠程交互的框架。
3)Why,為什么需要一個RPC框架,服務(wù)之間的調(diào)用需要各種場景和因素的考慮,內(nèi)部原理非常復(fù)雜和繁瑣,同時在集群情況下,服務(wù)的負載均衡,熔斷,限流等都是需要去考慮的,這時候就需要一個集服務(wù)注冊發(fā)現(xiàn)、負載均衡、序列化協(xié)議、RPC通信協(xié)議、Socket通信、異步調(diào)用、熔斷降級等技術(shù)為一體的技術(shù)去完成這些公共功能,RPC框架就是在這種情況下應(yīng)運而生。
目前比較主流的RPC框架包括谷歌開源的GRPC、阿里巴巴的Dubbo、Netflix 的SpringCloud等。
二、RPC框架基本組成
RPC框架需要的最基本的三個要素:
ServiceProvider: 服務(wù)提供方,提供相關(guān)服務(wù)接口。
ServiceConsumer: 服務(wù)消費方,消費服務(wù)提供方的接口。
Registry: 注冊中心,用于進行服務(wù)的注冊、發(fā)現(xiàn)、治理、高可用。
基于三個最基本要素,還會延伸出包括負載均衡器、熔斷降級器、通信協(xié)議組件、序列化協(xié)議等等組件。
一個最簡單的RPC調(diào)用模型圖如下所示:
下面做一些名詞的介紹和解釋:
2.1 注冊中心
注冊中心是RPC框架中的管理者和協(xié)調(diào)者角色,雖然在遠程過程調(diào)用中服務(wù)消費者會不經(jīng)過注冊中心,會直接向服務(wù)提供者發(fā)送請求,但是隨著我們的服務(wù)方越來越多,每個服務(wù)的實例也不斷變化的,且每個服務(wù)的地址,端口等信息是需要通知到消費方的,所以我們需要一個類似“管家”的角色,來負責(zé)管理服務(wù)注冊和發(fā)現(xiàn)的工作,這個“管家”我們稱之為注冊中心。
一個合格的注冊中心需要具備包括緩存和持久化服務(wù)提供方數(shù)據(jù),動態(tài)更新服務(wù)提供者信息,動態(tài)監(jiān)聽服務(wù)提供方節(jié)點變化,推送節(jié)點變化到消費方,查詢服務(wù)提供方數(shù)據(jù)等功能。
目前市面上比較流行的注冊中心有:Zookper、 Nacos、Consul、Eurake等,針對于上面功能的實現(xiàn)方式也有所不同,以下是注冊中心的對比:
|
Zookeeper |
Nacos |
Consul |
Eurake | |
|
一致性協(xié)議 |
CP |
CP + AP |
CP |
AP |
|
雪崩保護 |
無 |
有 |
無 |
有 |
|
多數(shù)據(jù)中心 |
不支持 |
支持 |
支持 |
支持 |
|
自動注銷實例 |
支持 |
支持 |
支持 |
支持 |
2.2 服務(wù)提供方(RPC服務(wù)端)
其需要對外提供服務(wù)接口,一個服務(wù)方需要包括啟動連接注冊中心,注冊相關(guān)信息到注冊中心,提供服務(wù)下線和更新機制,維護服務(wù)名和服務(wù)的映射,序列化和反序列化,啟動通信等。
目前服務(wù)提供方有兩種服務(wù)提供維度,基于接口的服務(wù)提供和基于服務(wù)的服務(wù)提供,Dubbo3.0 之前是基于接口維度做的服務(wù)注冊,Dubbo3.0之后漸漸向服務(wù)維度的服務(wù)注冊發(fā)現(xiàn)靠攏,SpringCloud是基于服務(wù)來進行注冊發(fā)現(xiàn)的,在云原生和容器化越來越火的今天,基于服務(wù)可以更好的適配容器化和云原生。
2.3 服務(wù)消費方(RPC消費端)
服務(wù)消費方需要具備可以從注冊中心拉取服務(wù)列表,緩存服務(wù)列表,動態(tài)監(jiān)聽和更新服務(wù)列表的功能,還需要具備針對于服務(wù)的負載均衡策略,序列化和反序列化,根據(jù)約定的通信協(xié)議進行調(diào)用等。
目前Dubbo是基于代理和Spring的BeanDefination來實現(xiàn)的,在消費啟動的時候會去掃描基于自定義注解或配置的信息,然后生成一個相應(yīng)的代理對象,注冊到Spring容器中,在調(diào)用的時候直接通過代理類進行相關(guān)一系列調(diào)用。SpringCloud是基于HTTP協(xié)議和增強版的RestTemplate來實現(xiàn)的,內(nèi)部實現(xiàn)了Ribbon的負載均衡,消費方可以通過Feign或者RestTemplate實現(xiàn)遠程調(diào)用。
2.4 通訊框架
通訊框架是服務(wù)之間進行IO交互和傳輸?shù)谋WC,消費端需要通過通訊框架和提供方進行交互,獲取數(shù)據(jù),目前市面上主流的基于Java的NIO通訊框架就是Netty。
2.5 通訊協(xié)議
通訊協(xié)議是消費端和服務(wù)端約定好一種交互協(xié)議,當(dāng)消費端拿到服務(wù)端提供的IO流之后,需要根據(jù)通訊協(xié)議獲取具體的數(shù)據(jù)內(nèi)容,目前TCP通訊協(xié)議比較通用的是HTTP、FTP、SMTP協(xié)議等,SpringCloud是基于HTTP的通訊協(xié)議實現(xiàn)的,Dubbo內(nèi)部自己集成了一套通訊協(xié)議。
業(yè)界的主流協(xié)議的解決方案可以歸納如下:
消息定長,例如每個報文的大小為固定長度100字節(jié),如果不夠用空格補足。
在包尾特殊結(jié)束符進行分割。
將消息分為消息頭和消息體,消息頭中包含表示消息總長度(或者消息體長度)的字段。
通過對比,我們發(fā)現(xiàn)第三點是最為靈活和可拓展的,一般推薦都會使用第三種。
2.6 序列化
2.6.1 概念介紹
序列化(serialization)就是將對象序列化為二進制形式(字節(jié)數(shù)組),一般也將序列化稱為編碼(Encode),主要用于網(wǎng)絡(luò)傳輸、數(shù)據(jù)持久化等。
反序列化(deserialization)則是將從網(wǎng)絡(luò)、磁盤等讀取的字節(jié)數(shù)組還原成原始對象,以便后續(xù)業(yè)務(wù)的進行,一般也將反序列化稱為解碼(Decode),用于網(wǎng)絡(luò)傳輸對象的解碼,以便完成遠程調(diào)用。
2.6.2 序列化協(xié)議XML & SOAP
XML是一種常用的序列化和反序列化協(xié)議,具有跨機器,跨語言等優(yōu)點。XML歷史悠久,其1.0版本早在1998年就形成標(biāo)準(zhǔn),并被廣泛使用至今,目前金融和銀行行業(yè)使用較多。
JSON
JSON 全程(Javascript Object Notation)起源于弱類型語言Javascript, 它的產(chǎn)生來自于一種稱之為”Associative array”的概念,其本質(zhì)是就是采用”Attribute-value”的方式來描述對象。實際上在Javascript和PHP等弱類型語言中,類的描述方式就是Associative array。JSON的具有數(shù)據(jù)簡單,可接受程度高,結(jié)構(gòu)簡潔,序列化包體小等特點,目前大部分的公司都是使用這種序列化協(xié)議來實現(xiàn)的。
Protobuf
由谷歌開發(fā)的一款高性能序列化框架,是一個純粹的展示層協(xié)議,可以和各種傳輸層協(xié)議一起使用,目前支持Java、C++、Python 等多種語言,他具有更小的數(shù)據(jù)量,更快的解析速度,簡單的調(diào)用等特點,目前得物使用的Dubbo2.7.7版本 默認使用這種序列化協(xié)議。
2.7 負載均衡
負載均衡是保證服務(wù)提供方在多實例的情況下保證負載的均衡的一種策略,目前大體有如下幾種負載均衡策略:
1)輪訓(xùn),采用計數(shù)器的方式,根據(jù)計數(shù)器的值和實例數(shù)量進行取余。
2)隨機,采用隨機請求的方式,隨機一個Random的數(shù)值,根據(jù)random進行取余。
3)加權(quán)輪訓(xùn),采用權(quán)重的方式,給每一個實例配置不同的權(quán)重比例,通過比例選擇合適的實例。
4) 一致性Hash,采用Hash環(huán)的方式,大體的實現(xiàn)思路是通過尋址的方式找到就近的一個節(jié)點,具體可以自行網(wǎng)上搜索一下相關(guān)文檔理解。
三、實現(xiàn)
既然是當(dāng)作練手實現(xiàn)一個RPC框架,所以會盡量借鑒當(dāng)前主流的框架,技術(shù)選型方面:
注冊中心:選擇Zookeeper來實現(xiàn)。
服務(wù)提供方:選擇基于服務(wù)維度來實現(xiàn)服務(wù)發(fā)現(xiàn),目前主流框架都是基于這個來做的。
服務(wù)消費方:選擇Dubbo類似的基于代理Spring的BeanDefination來實現(xiàn)。
通訊框架:Netty。
通訊協(xié)議:采用上述的第三種方式。
序列化協(xié)議:支持JSON 和 Protobuf。
負載均衡:實現(xiàn)輪訓(xùn)和隨機。
當(dāng)然,上述的組件都是使用SpringBoot的SPI方式來進行選擇的,后續(xù)如果需要進行拓展和按不同配置加載,可以通過配置的方式來實現(xiàn)插件的可插拔。
廢話不多說,先貼上項目整體結(jié)構(gòu):
整體代碼結(jié)構(gòu)如上,下面針對模塊一一講解:
3.1 注冊中心
代碼實現(xiàn)如下:
因為我們是以可拓展和接口方式實現(xiàn)的,所以我們定義了一些接口,通過不同的實現(xiàn)來進行區(qū)分,后期可以通過不同的配置來選擇合適的注冊中心。
3.2 服務(wù)提供方
服務(wù)提供方通過使用Spring的事件來進行監(jiān)聽,同時根據(jù)聲明式的注解來進行解析和注冊,同時通過組裝元數(shù)據(jù),將自己的服務(wù)注冊到注冊中心,完成服務(wù)提供方的服務(wù)注冊,同時啟動Netty的客戶端,來進行客戶端的監(jiān)聽,從而進行服務(wù)調(diào)用,具體流程圖如下:
部分實現(xiàn)代碼如下:
自動裝備邏輯:
使用和服務(wù)注冊邏輯:
3.3 服務(wù)消費方
服務(wù)消費方的邏輯稍微復(fù)雜一些,需要通過自動裝配來創(chuàng)建新的BeanDefination, 然后從所有的Bean中找到相關(guān)的帶有RPC注解的參數(shù),重寫B(tài)eanDefination,重寫的Bean需要構(gòu)建新的元數(shù)據(jù)和存入客戶端緩存,然后通過動態(tài)代理的方式,創(chuàng)建一個代理對象,對象使用負載均衡在服務(wù)發(fā)現(xiàn)的時候選擇一個地址,通過Netty的方式進行通信和數(shù)據(jù)交互,最后返回相關(guān)數(shù)據(jù)對象,具體的流程如下圖:
部分實現(xiàn)代碼如下:
啟動開始類代碼:
代理類實現(xiàn)代碼:
負載均衡實現(xiàn)代碼:(SPI可拓展模式)
目前采用輪訓(xùn)和隨機的方式實現(xiàn)的,后期可根據(jù)接口進行拓展。
3.4 通訊框架
我們使用Netty4實現(xiàn)了通訊框架,采用了NettyClient和NettyServer來實現(xiàn):
3.5 通訊協(xié)議
我們目前使用了自定義的通信協(xié)議來實現(xiàn):
第一個字節(jié)是魔法數(shù),比如我定義為0X35。
第二個字節(jié)代表協(xié)議版本號,以便對協(xié)議進行擴展,使用不同的協(xié)議解析器。
第三個字節(jié)是請求類型,如0代表請求1代表響應(yīng)。
第四個字節(jié)表示消息長度,即此四個字節(jié)后面此長度的內(nèi)容是消息content。
3.6 序列化協(xié)議
目前支持JSON和ProtoBuf,后期我們可以通過SPI進行拓展和可配置。
整體核心調(diào)用流程:
四、總結(jié)
本文從整體名詞介紹、內(nèi)部組件組件介紹等兩個方面闡述了RPC的框架模型,從技術(shù)選型、具體代碼等實現(xiàn)了一個RPC框架并應(yīng)用到項目中。目前RPC框架整體搭建完成,可以正常通過注解接入業(yè)務(wù)方使用,但還有很多細節(jié)需要更仔細地去考慮和思索,比如系統(tǒng)的可拓展性和框架的整體性能等。希望通過閱讀本篇文章,可以讓讀者對RPC有更清晰的了解,讓自己的基礎(chǔ)技能有一個更高的提升。
分享標(biāo)題:帶你手把手實操一個RPC框架
網(wǎng)站鏈接:http://fisionsoft.com.cn/article/cogshci.html


咨詢
建站咨詢
