日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

dubbo协议_Dubbo协议解析与OPPO自研ESA RPC框架实践

發(fā)布時(shí)間:2024/7/23 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 dubbo协议_Dubbo协议解析与OPPO自研ESA RPC框架实践 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
本文來自O(shè)PPO互聯(lián)網(wǎng)基礎(chǔ)技術(shù)團(tuán)隊(duì),轉(zhuǎn)載請注名作者。同時(shí)歡迎關(guān)注我們的公眾號:OPPO_tech,與你分享OPPO前沿互聯(lián)網(wǎng)技術(shù)及活動。

1. 背景

Dubbo是一款高性能、輕量級的開源Java RPC框架,誕生于2012年,2015年停止研發(fā),后來重啟并發(fā)布了2.7及連續(xù)多個(gè)版本。Dubbo自開源以來,許多大公司都以此為微服務(wù)架構(gòu)基石,甚至在官方停止維護(hù)的幾年中,熱度依然不減。

但最近幾年云原生技術(shù)開始成為主流,與Dubbo框架的核心設(shè)計(jì)理念有不相容之處,再加上公司安全治理的需求,OPPO互聯(lián)網(wǎng)技術(shù)團(tuán)隊(duì)開發(fā)了面向云原生、 Mesh友好的ESA RPC框架。

2.Dubbo協(xié)議解析

協(xié)議是兩個(gè)網(wǎng)絡(luò)實(shí)體進(jìn)行通信的基礎(chǔ),數(shù)據(jù)在網(wǎng)絡(luò)上從一個(gè)實(shí)體傳輸?shù)搅硪粋€(gè)實(shí)體,以字節(jié)流的形式傳遞到對端。Dubbo協(xié)議由服務(wù)提供者與消費(fèi)者雙端約定,需要確定的是一次有意義的傳輸內(nèi)容在讀到何時(shí)結(jié)束,因?yàn)橐粋€(gè)一個(gè)byte傳輸過來,需要有一個(gè)結(jié)束。而且數(shù)據(jù)在網(wǎng)絡(luò)上的傳輸,存在粘包和半包的情況,能夠應(yīng)對這個(gè)問題的辦法就是協(xié)議能夠準(zhǔn)確的識別,當(dāng)粘包發(fā)生時(shí)不會多讀,當(dāng)半包發(fā)生時(shí)會繼續(xù)讀取。

2.1 Dubbo Header內(nèi)容

Dubbo header的長度總共16字節(jié),128位,如下圖所示:

  • Magic(16 bits) : 協(xié)議魔數(shù),標(biāo)識Dubbo 數(shù)據(jù)包。
  • Req/Res(1 bit) : 標(biāo)識請求或者相應(yīng)。請求:1,相應(yīng):0。
  • Two Way(1 bit) : 僅在 Req/Res 為1(請求)時(shí)才有用,標(biāo)記是否期望從服務(wù)器返回值。如果需要來自服務(wù)器的返回值,則設(shè)置為1。
  • Event(1 bit) : 標(biāo)識是否是事件消息,例如,心跳事件。如果這是一個(gè)事件,則設(shè)置為1。
  • SerializationId(5 bits) : 序列化id。
  • Status(8 bits) : 僅在 Req/Res 為0(響應(yīng))時(shí)有用,用于標(biāo)識響應(yīng)的狀態(tài)。
  • RequstId(64 bits) : 標(biāo)識唯一請求。類型為long。
  • Data length(32 bits) : 序列化后的內(nèi)容長度(變長部分,即不包含header),按字節(jié)計(jì)數(shù)。通過payload參數(shù)指定,默認(rèn)為8M。

2.2 Dubbo body內(nèi)容

Dubbo 數(shù)據(jù)包的body 部分內(nèi)容,分為請求包與響應(yīng)包。

如果是請求包,則包含的部分有:

  • dubbo協(xié)議版本號(2.0.2);
  • 接口名;
  • 接口版本號;
  • 方法名;
  • 方法參數(shù)類型;
  • 方法參數(shù);
  • 附件(Attachment):
    • 接口分組(group);
    • 接口版本號(version);
    • 接口名;
    • 自定義附件參數(shù);

如果是響應(yīng)包,則包含的內(nèi)容有:

  • 返回值類型(byte):
    • 返回空值(2);
    • 正常返回值(1);
    • 異常(0);
  • 返回值;

通過對dubbo協(xié)議的解析,我們可以知道,dubbo協(xié)議是一個(gè)Header定長的變長協(xié)議。這也在我們ESA RPC實(shí)踐過程中提供了一些思路。

2.3 Dubbo協(xié)議優(yōu)缺點(diǎn)

2.3.1 優(yōu)點(diǎn)

Dubbo協(xié)議的設(shè)計(jì)非常緊湊、簡單,盡可能的減少傳輸包大小,能用一個(gè)bit表示的字段,不會用一個(gè)byte。

2.3.2 不足

  • 請求body中某些字段重復(fù)傳遞(如接口名,接口版本號),即body內(nèi)容與附件attachment 中存在重復(fù)字段,增大傳輸數(shù)據(jù)包大小;
  • 對于ServiceMesh 場景很不友好。在ServiceMesh 場景中,會將原sdk中的大部分功能遷移至SideCar 中實(shí)現(xiàn),這里以服務(wù)發(fā)現(xiàn)為例。Dubbo 中的服務(wù)發(fā)現(xiàn),是通過接口名
    (interfaceName)、接口分組(group)、接口版本號(version)三者定位一個(gè)唯一服務(wù),也是服務(wù)發(fā)現(xiàn)的關(guān)鍵要素,但是我們從dubbo body內(nèi)容可知,必須要將完整的數(shù)據(jù)包全部解析(attachment位于body末),才能獲取到這三個(gè)要素,這是完全沒必要的。
  • 沒有預(yù)留字段,擴(kuò)展性不足。

3. Dubbo的現(xiàn)狀

Dubbo自開源以來,在業(yè)內(nèi)造成了巨大的影響,許多公司甚至大廠都以此為微服務(wù)架構(gòu)基石,甚至在Dubbo官方停止維護(hù)的幾年中,熱度依然不減,足以證明其本身的優(yōu)秀。

在這過程中,Dubbo協(xié)議的內(nèi)容一直沒有太大變化,主要是為了兼容性考慮,但其他內(nèi)容,隨著Dubbo的發(fā)展變化卻是很大。這里我們主要聊一聊dubbo從2.7.0版本以后的情況。

3.1 Dubbo 2.7.x版本總覽

這是dubbo自2.7.0版本以來,各個(gè)版本的簡要功能說明,以及升級建議??梢钥吹絛ubbo官方推薦生產(chǎn)使用的只有2.7.3 和2.7.4.1兩個(gè)版本。但這兩個(gè)推薦版本,也有不能滿足需求的地方。

由于dubbo在2.7.3 和2.7.4.1 這兩個(gè)版本中改動巨大,使得這兩個(gè)版本無法向下兼容,這讓基于其他版本做的一些dubbo擴(kuò)展幾乎無法使用。升級dubbo的同時(shí),還需要將以前的擴(kuò)展全部檢查修改一遍,這帶來很大工作量。而且除了我們自身團(tuán)隊(duì)的一些公共擴(kuò)展外,全公司其他業(yè)務(wù)團(tuán)隊(duì)很可能還有自己的一些擴(kuò)展,這無疑增大了我們升級dubbo的成本。

4. ESA RPC最佳實(shí)踐

最近幾年云原生技術(shù)開始成為主流,與Dubbo框架的核心設(shè)計(jì)理念也有不相容之處,再加上公司安全治理的需求,我們需要一款面向云原生、 Mesh友好的RPC框架。

在這個(gè)背景下,OPPO互聯(lián)網(wǎng)技術(shù)團(tuán)隊(duì)從2019年下半年開始動手設(shè)計(jì)開發(fā)ESA RPC,到2020年一季度,ESA RPC 第一版成功發(fā)布。下面我們簡單介紹下ESA RPC的一些主要功能。

4.1 實(shí)例級服務(wù)注冊與發(fā)現(xiàn)

ESA RPC通過深度整合發(fā)布平臺,實(shí)現(xiàn)實(shí)例級服務(wù)注冊與發(fā)現(xiàn),如圖所示:

應(yīng)用發(fā)布時(shí),相應(yīng)的發(fā)布平臺會將實(shí)例信息注冊到OPPO自研的注冊中心ESA Registry(應(yīng)用本身則不再進(jìn)行注冊),注冊信息包含應(yīng)用名、ip、端口、實(shí)例編號等等,消費(fèi)者啟動時(shí)只需通過應(yīng)用編號訂閱相關(guān)提供者即可。

既然服務(wù)注冊部分是由發(fā)布平臺完成,開發(fā)者在發(fā)布應(yīng)用時(shí),就需要填寫相關(guān)信息,即相關(guān)的暴露協(xié)議以及對應(yīng)的端口,這樣發(fā)布平臺才可以正確注冊提供者信息。

4.2 客戶端線程模型優(yōu)化

ESA RPC全面擁抱java8的CompletableFuture ,我們將同步和異步的請求統(tǒng)一處理,認(rèn)為同步是特殊的異步。而Dubbo,由于歷史原因,最初dubbo使用的jdk版本還是1.7,所以在客戶端的線程模型中,為了不阻塞IO線程,dubbo增加了一個(gè)Cached線程池,所有的IO消息統(tǒng)一都通知到這個(gè)Cached線程池中,然后再切換回相應(yīng)的業(yè)務(wù)線程,這樣可能會造成當(dāng)請求并發(fā)較高時(shí),客戶端線程暴漲問題,進(jìn)而導(dǎo)致客戶端性能低下。

所以我們在ESA RPC客戶端優(yōu)化了線程模型,將原有的dubbo客戶端cached線程池取消,改為如下圖模型:

具體做法:

  • 當(dāng)前業(yè)務(wù)線程發(fā)出遠(yuǎn)程調(diào)用請求后,生成CompletableFuture 對象,并傳遞至IO線程,等待返
    回;
  • IO線程收到返回內(nèi)容后,找到與之對應(yīng)的CompletableFuture 對象,直接賦予其返回內(nèi)容;
  • 業(yè)務(wù)線程通過自己生成的CompletableFuture 對象獲取返回值;

4.3 智能Failover

對于一些高并發(fā)的服務(wù),可能會因傳統(tǒng)Failover 中的重試而導(dǎo)致服務(wù)雪崩。ESA RPC對此進(jìn)行優(yōu)化,采用基于請求失敗率的Failover ,即當(dāng)請求失敗率低于相應(yīng)閾值時(shí),執(zhí)行正常的failover重試策略,而當(dāng)失敗率超過閾值時(shí),則停止進(jìn)行重試,直到失敗率低于閾值再恢復(fù)重試功能。

ESA RPC采用RingBuffer 的數(shù)據(jù)結(jié)構(gòu)記錄請求狀態(tài),成功為0,失敗為1。用戶可通過配置的方式指定該RingBuffer 的長度,以及請求失敗率閾值。

4.4 ServiceKeeper

ESA ServiceKeeper (以下簡稱ServiceKeeper ),屬于OPPO自研的基礎(chǔ)框架技術(shù)棧ESA Stack系列的一員。ServiceKeeper 是一款輕量級的服務(wù)治理框架,通過攔截并代理原始方法的方式織入限流、并發(fā)數(shù)限制、熔斷、降級等功能。

ServiceKeeper 支持方法和參數(shù)級的服務(wù)治理以及動態(tài)動態(tài)更新配置等功能,包括:

  • 方法隔離
  • 方法限流
  • 方法熔斷
  • 方法降級
  • 參數(shù)級隔離、限流、熔斷
  • 方法重試
  • 接口分組
  • 動態(tài)更新配置,實(shí)時(shí)生效

ESA RPC中默認(rèn)使用ServiceKeeper 來實(shí)現(xiàn)相關(guān)服務(wù)治理內(nèi)容,使用起來也相對簡單。

Step 1

application.properties 文件中開啟ServiceKeeper 功能。

# 開啟服務(wù)端 esa.rpc.provider.parameter.enable-service-keeper=true# 開啟客戶端 esa.rpc.consumer.parameter.enable-service-keeper=true

Step 2

新增service-keeper.properties 配置文件,并按照如下規(guī)則進(jìn)行配置:

# 接口級配置規(guī)則:{interfaceName}/{version}/{group}.{serviceKeeper params},示例: com.oppo.dubbo.demo.DemoService/0.0.1/group1.maxConcurrentLimit=20 com.oppo.dubbo.demo.DemoService/0.0.1/group1.failureRateThreshold=55.5 com.oppo.dubbo.demo.DemoService/0.0.1/group1.forcedOpen=55.5 ...#方法級動態(tài)配置規(guī)則:{interfaceName}/{version}/{group}.{methodName}.{serviceKeeper params},示例: com.oppo.dubbo.demo.DemoService/0.0.1/group1.sayHello.maxConcurrentLimit=20 com.oppo.dubbo.demo.DemoService/0.0.1/group1.sayHello.maxConcurrentLimit=20 com.oppo.dubbo.demo.DemoService/0.0.1/group1.sayHello.failureRateThreshold=55.5 com.oppo.dubbo.demo.DemoService/0.0.1/group1.sayHello.forcedOpen=false com.oppo.dubbo.demo.DemoService/0.0.1/group1.sayHello.limitForPeriod=600 ...#參數(shù)級動態(tài)配置規(guī)則:{interfaceName}/{version}/{group}.{methodName}.參數(shù)別名.配置名稱=配置值列表,示例: com.oppo.dubbo.demo.DemoService/0.0.1/group1.sayHello.arg0.limitForPeriod={LiSi:20,ZhangSan:50} ...

4.5 連接管理

ESA RPC中,一個(gè)消費(fèi)者與一個(gè)提供者,默認(rèn)只會創(chuàng)建一個(gè)連接,但是允許用戶通過配置創(chuàng)建多個(gè),配置項(xiàng)為connections (與dubbo保持一致)。ESA RPC的連接池通過公司內(nèi)部一個(gè)全異步對象池管理庫commons pool來達(dá)到對連接的管理,其中連接的創(chuàng)建、銷毀等操作均為異步執(zhí)行,避免阻塞線程,提升框架整體性能。

需要注意的是,這里的建連過程,有一個(gè)并發(fā)問題要解決: 當(dāng)客戶端在高并發(fā)的調(diào)用建連方法時(shí),如何保證建立的連接剛好是所設(shè)定的個(gè)數(shù)呢?為了配合 Netty 的無鎖理念,我們也采用一個(gè)無鎖化的建連過程來實(shí)現(xiàn),利用 ConcurrentHashMap 的putIfAbsent 方法:

AcquireTask acquireTask = this.pool.get(idx); if (acquireTask == null) {acquireTask = new AcquireTask();AcquireTask tmpTask = this.pool.putIfAbsent(idx, acquireTask);if (tmpTask == null) {acquireTask.create(); //執(zhí)行真正的建連操作} }

4.6 gRPC協(xié)議支持

由于ESA RPC默認(rèn)使用ESA Regsitry 作為注冊中心,由上述實(shí)例注冊部分可知,服務(wù)注冊通過發(fā)布平
臺來完成,所以ESA RPC對于gRPC協(xié)議的支持具有天然的優(yōu)勢,即服務(wù)的提供者可以不接入任何sdk,甚至可以是其他非java語言,只需要通過公司發(fā)布平臺發(fā)布應(yīng)用后,就可以注冊至注冊中心,消費(fèi)者也就可以進(jìn)行訂閱消費(fèi)。

這里我們以消費(fèi)端為例,來介紹ESA RPC客戶端如何請求gRPC服務(wù)端。

proto文件定義:

syntax = "proto3";option java_multiple_files = false; option java_outer_classname = "HelloWorld"; option objc_class_prefix = "HLW";package esa.rpc.grpc.test.service;// The greeting service definition. service GreeterService {// Sends a greetingrpc sayHello (HelloRequest) returns (HelloReply) {} }service DemoService {// Sends a greetingrpc sayHello (HelloRequest) returns (HelloReply) {} }// The request message containing the user's name. message HelloRequest {string name = 1; }// The response message containing the greetings message HelloReply {string message = 1; }

然后maven中添加proto代碼生成插件:

<build><extensions><extension><groupId>kr.motd.maven</groupId><artifactId>os-maven-plugin</artifactId><version>1.5.0.Final</version></extension></extensions><plugins><plugin><groupId>org.xolstice.maven.plugins</groupId><artifactId>protobuf-maven-plugin</artifactId><version>0.5.0</version><configuration><protocArtifact>com.google.protobuf:protoc:3.11.0:exe:${os.detected.classifier} </protocArtifact><pluginId>grpc-java</pluginId><pluginArtifact>esa.rpc:protoc-gen-grpc-java:1.0.0- SNAPSHOT:exe:${os.detected.classifier}</pluginArtifact></configuration><executions><execution><goals><goal>compile</goal><goal>compile-custom</goal></goals></execution></executions></plugin></plugins></build>

如上proto定義文件,通過protobuf:compile和protobuf:compile-custom則會生成如下代碼:

可以看到,自動生成的代碼中我們額外生成了相應(yīng)的java接口。

在dubbo客戶端我們就可以直接使用這個(gè)接口進(jìn)行遠(yuǎn)程調(diào)用,使用方式:

@Reference(...,protocol="grpc") private DemoService demoService;

4.7 ESA RPC性能

這里僅舉一例,展示ESA RPC性能。

5. ESA RPC未來規(guī)劃

5.1 ESA RPC如何進(jìn)行平滑遷移?

由于歷史原因,現(xiàn)公司內(nèi)部大量使用的是Dubbo作為RPC框架,以及zookeeper注冊中心,如何能夠保證業(yè)務(wù)的平滑遷移,一直是我們在思考的問題。這個(gè)問題想要解答,主要分為以下兩點(diǎn)。

5.1.1 代碼層面

在代碼層面,ESA RPC考慮到這個(gè)歷史原因,盡可能的兼容dubbo,盡可能降低遷移成本。但ESA RPC畢竟作為一款新的RPC框架,想要零成本零改動遷移是不可能的,但在沒有dubbo擴(kuò)展的情況下,改動很小。

5.1.2 整體架構(gòu)

這一點(diǎn)我們舉例說明,當(dāng)業(yè)務(wù)方遷移某一應(yīng)用至ESA RPC框架時(shí),該應(yīng)用中消費(fèi)ABCD四個(gè)接口,但這些接口的服務(wù)提供者應(yīng)用并未升級至ESA RPC,接口元數(shù)據(jù)信息均保存至zookeeper注冊中心當(dāng)中,而ESA RPC推薦使用的ESA Registry注冊中心中沒有這些提供者信息,這就導(dǎo)致了消費(fèi)者無法消費(fèi)這些老的提供者信息。

針對這一問題,后續(xù)我們ESA Stack系列會提供相應(yīng)的數(shù)據(jù)同步工具,將原zookeeper注冊中心中的服務(wù)元數(shù)據(jù)信息同步到我們ESA Registry中,而zookeeper中的這些信息暫時(shí)不刪除(以便老的接口消費(fèi)者能夠消費(fèi)),等待均升級完成后,即可停用zookeeper注冊中心。

5.2 自研RPC協(xié)議

在上面Dubbo協(xié)議解析過程中,我們分析了Dubbo協(xié)議的優(yōu)缺點(diǎn),了解了Dubbo協(xié)議的不足。所以后續(xù)的版本升級過程中,自研RPC協(xié)議是一個(gè)不可忽視的內(nèi)容。自研RPC協(xié)議需要充分考慮安全、性能、Mesh支持、可擴(kuò)展、兼容性等因素,相信通過自研RPC協(xié)議可以使我們的ESA RPC更上一層樓。

5.3 其他

  • 多協(xié)議暴露
  • 同機(jī)房優(yōu)先路由
  • 類隔離
  • ...

在這篇文章中,我們主要分享了Dubbo協(xié)議的分析以及ESA RPC的實(shí)踐內(nèi)容,后續(xù)OPPO互聯(lián)網(wǎng)技術(shù)團(tuán)隊(duì)會繼續(xù)分享更多ESA RPC的動態(tài)。

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

總結(jié)

以上是生活随笔為你收集整理的dubbo协议_Dubbo协议解析与OPPO自研ESA RPC框架实践的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。