Dubbo3 RPC 通信協(xié)議

2022-03-29 15:09 更新

描述 Dubbo3 支持的通信協(xié)議

Dubbo3 提供了 Triple(Dubbo3)、Dubbo2 協(xié)議,這是 Dubbo 框架的原生協(xié)議。除此之外,Dubbo3 也對(duì)眾多第三方協(xié)議進(jìn)行了集成,并將它們納入 Dubbo 的編程與服務(wù)治理體系, 包括 gRPC、Thrift、JsonRPC、Hessian2、REST 等。以下重點(diǎn)介紹 Triple 與 Dubbo2 協(xié)議。

Triple 協(xié)議

Triple 協(xié)議是 Dubbo3 推出的主力協(xié)議。Triple 意為第三代,通過(guò) Dubbo1.0/ Dubbo2.0 兩代協(xié)議的演進(jìn),以及云原生帶來(lái)的技術(shù)標(biāo)準(zhǔn)化浪潮,Dubbo3 新協(xié)議 Triple 應(yīng)運(yùn)而生。

RPC 協(xié)議的選擇

協(xié)議是 RPC 的核心,它規(guī)范了數(shù)據(jù)在網(wǎng)絡(luò)中的傳輸內(nèi)容和格式。除必須的請(qǐng)求、響應(yīng)數(shù)據(jù)外,通常還會(huì)包含額外控制數(shù)據(jù),如單次請(qǐng)求的序列化方式、超時(shí)時(shí)間、壓縮方式和鑒權(quán)信息等。

協(xié)議的內(nèi)容包含三部分

  • 數(shù)據(jù)交換格式: 定義 RPC 的請(qǐng)求和響應(yīng)對(duì)象在網(wǎng)絡(luò)傳輸中的字節(jié)流內(nèi)容,也叫作序列化方式
  • 協(xié)議結(jié)構(gòu): 定義包含字段列表和各字段語(yǔ)義以及不同字段的排列方式
  • 協(xié)議通過(guò)定義規(guī)則、格式和語(yǔ)義來(lái)約定數(shù)據(jù)如何在網(wǎng)絡(luò)間傳輸。一次成功的 RPC 需要通信的兩端都能夠按照協(xié)議約定進(jìn)行網(wǎng)絡(luò)字節(jié)流的讀寫(xiě)和對(duì)象轉(zhuǎn)換。如果兩端對(duì)使用的協(xié)議不能達(dá)成一致,就會(huì)出現(xiàn)雞同鴨講,無(wú)法滿足遠(yuǎn)程通信的需求。


RPC 協(xié)議的設(shè)計(jì)需要考慮以下內(nèi)容:

  • 通用性: 統(tǒng)一的二進(jìn)制格式,跨語(yǔ)言、跨平臺(tái)、多傳輸層協(xié)議支持
  • 擴(kuò)展性: 協(xié)議增加字段、升級(jí)、支持用戶(hù)擴(kuò)展和附加業(yè)務(wù)元數(shù)據(jù)
  • 性能:As fast as it can be
  • 穿透性:能夠被各種終端設(shè)備識(shí)別和轉(zhuǎn)發(fā):網(wǎng)關(guān)、代理服務(wù)器等 通用性和高性能通常無(wú)法同時(shí)達(dá)到,需要協(xié)議設(shè)計(jì)者進(jìn)行一定的取舍。

HTTP/1.1

比于直接構(gòu)建于 TCP 傳輸層的私有 RPC 協(xié)議,構(gòu)建于 HTTP 之上的遠(yuǎn)程調(diào)用解決方案會(huì)有更好的通用性,如WebServices 或 REST 架構(gòu),使用 HTTP + JSON 可以說(shuō)是一個(gè)事實(shí)標(biāo)準(zhǔn)的解決方案。

選擇構(gòu)建在 HTTP 之上,有兩個(gè)最大的優(yōu)勢(shì):

  • HTTP 的語(yǔ)義和可擴(kuò)展性能很好的滿足 RPC 調(diào)用需求。
  • 通用性,HTTP 協(xié)議幾乎被網(wǎng)絡(luò)上的所有設(shè)備所支持,具有很好的協(xié)議穿透性。

但也存在比較明顯的問(wèn)題:

  • 典型的 Request – Response 模型,一個(gè)鏈路上一次只能有一個(gè)等待的 Request 請(qǐng)求。會(huì)產(chǎn)生 HOL。
  • Human Readable Headers,使用更通用、更易于人類(lèi)閱讀的頭部傳輸格式,但性能相當(dāng)差
  • 無(wú)直接 Server Push 支持,需要使用 Polling Long-Polling 等變通模式

gRPC

上面提到了在 HTTP 及 TCP 協(xié)議之上構(gòu)建 RPC 協(xié)議各自的優(yōu)缺點(diǎn),相比于 Dubbo 構(gòu)建于 TCP 傳輸層之上,Google 選擇將 gRPC 直接定義在 HTTP/2 協(xié)議之上。 gRPC 的優(yōu)勢(shì)由HTTP2 和 Protobuf 繼承而來(lái)。

  • 基于 HTTP2 的協(xié)議足夠簡(jiǎn)單,用戶(hù)學(xué)習(xí)成本低,天然有 server push/ 多路復(fù)用 / 流量控制能力
  • 基于 Protobuf 的多語(yǔ)言跨平臺(tái)二進(jìn)制兼容能力,提供強(qiáng)大的統(tǒng)一跨語(yǔ)言能力
  • 基于協(xié)議本身的生態(tài)比較豐富,k8s/etcd 等組件的天然支持協(xié)議,云原生的事實(shí)協(xié)議標(biāo)準(zhǔn)

但是也存在部分問(wèn)題

  • 對(duì)服務(wù)治理的支持比較基礎(chǔ),更偏向于基礎(chǔ)的 RPC 功能,協(xié)議層缺少必要的統(tǒng)一定義,對(duì)于用戶(hù)而言直接用起來(lái)并不容易。
  • 強(qiáng)綁定 protobuf 的序列化方式,需要較高的學(xué)習(xí)成本和改造成本,對(duì)于現(xiàn)有的偏單語(yǔ)言的用戶(hù)而言,遷移成本不可忽視

最終的選擇 Triple

最終我們選擇了兼容 gRPC ,以 HTTP2 作為傳輸層構(gòu)建新的協(xié)議,也就是 Triple。

容器化應(yīng)用程序和微服務(wù)的興起促進(jìn)了針對(duì)負(fù)載內(nèi)容優(yōu)化技術(shù)的發(fā)展。 客戶(hù)端中使用的傳統(tǒng)通信協(xié)議( RESTFUL或其他基于 HTTP 的自定義協(xié)議)難以滿足應(yīng)用在性能、可維護(hù)性、擴(kuò)展性、安全性等方便的需求。一個(gè)跨語(yǔ)言、模塊化的協(xié)議會(huì)逐漸成為新的應(yīng)用開(kāi)發(fā)協(xié)議標(biāo)準(zhǔn)。自從 2017 年 gRPC 協(xié)議成為 CNCF 的項(xiàng)目后,包括 k8s、etcd 等越來(lái)越多的基礎(chǔ)設(shè)施和業(yè)務(wù)都開(kāi)始使用 gRPC 的生態(tài),作為云原生的微服務(wù)化框架, Dubbo 的新協(xié)議也完美兼容了 gRPC。并且,對(duì)于 gRPC 協(xié)議中一些不完善的部分, Triple 也將進(jìn)行增強(qiáng)和補(bǔ)充。

那么,Triple 協(xié)議是否解決了上面我們提到的一系列問(wèn)題呢?

  • 性能上: Triple 協(xié)議采取了 metadata 和 payload 分離的策略,這樣就可以避免中間設(shè)備,如網(wǎng)關(guān)進(jìn)行 payload 的解析和反序列化,從而降低響應(yīng)時(shí)間。
  • 路由支持上,由于 metadata 支持用戶(hù)添加自定義 header ,用戶(hù)可以根據(jù) header 更方便的劃分集群或者進(jìn)行路由,這樣發(fā)布的時(shí)候切流灰度或容災(zāi)都有了更高的靈活性。
  • 安全性上,支持雙向TLS認(rèn)證(mTLS)等加密傳輸能力。
  • 易用性上,Triple 除了支持原生 gRPC 所推薦的 Protobuf 序列化外,使用通用的方式支持了 Hessian / JSON 等其他序列化,能讓用戶(hù)更方便的升級(jí)到 Triple 協(xié)議。對(duì)原有的 Dubbo 服務(wù)而言,修改或增加 Triple 協(xié)議 只需要在聲明服務(wù)的代碼塊添加一行協(xié)議配置即可,改造成本幾乎為 0。

Triple 協(xié)議


  • 現(xiàn)狀

1、完整兼容grpc、客戶(hù)端/服務(wù)端可以與原生grpc客戶(hù)端打通

2、目前已經(jīng)經(jīng)過(guò)大規(guī)模生產(chǎn)實(shí)踐驗(yàn)證,達(dá)到生產(chǎn)級(jí)別

  • 特點(diǎn)與優(yōu)勢(shì)

1、具備跨語(yǔ)言互通的能力,傳統(tǒng)的多語(yǔ)言多 SDK 模式和 Mesh 化跨語(yǔ)言模式都需要一種更通用易擴(kuò)展的數(shù)據(jù)傳輸格式。

2、提供更完善的請(qǐng)求模型,除了 Request/Response 模型,還應(yīng)該支持 Streaming 和 Bidirectional。

3、易擴(kuò)展、穿透性高,包括但不限于 Tracing / Monitoring 等支持,也應(yīng)該能被各層設(shè)備識(shí)別,網(wǎng)關(guān)設(shè)施等可以識(shí)別數(shù)據(jù)報(bào)文,對(duì) Service Mesh 部署友好,降低用戶(hù)理解難度。

4、多種序列化方式支持、平滑升級(jí)

5、支持 Java 用戶(hù)無(wú)感知升級(jí),不需要定義繁瑣的 IDL 文件,僅需要簡(jiǎn)單的修改協(xié)議名便可以輕松升級(jí)到 Triple 協(xié)議

Triple 協(xié)議內(nèi)容介紹

基于 grpc 協(xié)議進(jìn)行進(jìn)一步擴(kuò)展

  • Service-Version → “tri-service-version” {Dubbo service version}
  • Service-Group → “tri-service-group” {Dubbo service group}
  • Tracing-ID → “tri-trace-traceid” {tracing id}
  • Tracing-RPC-ID → “tri-trace-rpcid” {_span id _}
  • Cluster-Info → “tri-unit-info” {cluster infomation}

其中 Service-Version 跟 Service-Group 分別標(biāo)識(shí)了 Dubbo 服務(wù)的 version 跟 group 信息,因?yàn)間rpc的 path 申明了 service name 跟 method name,相比于 Dubbo 協(xié)議,缺少了version 跟 group 信息;Tracing-ID、Tracing-RPC-ID 用于全鏈路追蹤能力,分別表示 tracing id 跟 span id 信息;Cluster-Info 表示集群信息,可以使用其構(gòu)建一些如集群劃分等路由相關(guān)的靈活的服務(wù)治理能力。

Triple Streaming

Triple協(xié)議相比傳統(tǒng)的unary方式,多了目前提供的Streaming RPC的能力

  • Streaming 用于什么場(chǎng)景呢?

在一些大文件傳輸、直播等應(yīng)用場(chǎng)景中, consumer或provider需要跟對(duì)端進(jìn)行大量數(shù)據(jù)的傳輸,由于這些情況下的數(shù)據(jù)量是非常大的,因此是沒(méi)有辦法可以在一個(gè)RPC的數(shù)據(jù)包中進(jìn)行傳輸,因此對(duì)于這些數(shù)據(jù)包我們需要對(duì)數(shù)據(jù)包進(jìn)行分片之后,通過(guò)多次RPC調(diào)用進(jìn)行傳輸,如果我們對(duì)這些已經(jīng)拆分了的RPC數(shù)據(jù)包進(jìn)行并行傳輸,那么到對(duì)端后相關(guān)的數(shù)據(jù)包是無(wú)序的,需要對(duì)接收到的數(shù)據(jù)進(jìn)行排序拼接,相關(guān)的邏輯會(huì)非常復(fù)雜。但如果我們對(duì)拆分了的RPC數(shù)據(jù)包進(jìn)行串行傳輸,那么對(duì)應(yīng)的網(wǎng)絡(luò)傳輸RTT與數(shù)據(jù)處理的時(shí)延會(huì)是非常大的。

為了解決以上的問(wèn)題,并且為了大量數(shù)據(jù)的傳輸以流水線方式在consumer與provider之間傳輸,因此Streaming RPC的模型應(yīng)運(yùn)而生。

通過(guò)Triple協(xié)議的Streaming RPC方式,會(huì)在consumer跟provider之間建立多條用戶(hù)態(tài)的長(zhǎng)連接,Stream。同一個(gè)TCP連接之上能同時(shí)存在多個(gè)Stream,其中每條Stream都有StreamId進(jìn)行標(biāo)識(shí),對(duì)于一條Stream上的數(shù)據(jù)包會(huì)以順序方式讀寫(xiě)。

總結(jié)

在API領(lǐng)域,最重要的趨勢(shì)是標(biāo)準(zhǔn)化技術(shù)的崛起。Triple 協(xié)議是 Dubbo3 推出的主力協(xié)議。它采用分層設(shè)計(jì),其數(shù)據(jù)交換格式基于Protobuf (Protocol Buffers) 協(xié)議開(kāi)發(fā),具備優(yōu)秀的序列化/反序列化效率,當(dāng)然還支持多種序列化方式,也支持眾多開(kāi)發(fā)語(yǔ)言。在傳輸層協(xié)議,Triple 選擇了 HTTP/2,相較于 HTTP/1.1,其傳輸效率有了很大提升。此外HTTP/2作為一個(gè)成熟的開(kāi)放標(biāo)準(zhǔn),具備豐富的安全、流控等能力,同時(shí)擁有良好的互操作性。Triple 不僅可以用于Server端服務(wù)調(diào)用,也可以支持瀏覽器、移動(dòng)App和IoT設(shè)備與后端服務(wù)的交互,同時(shí) Triple協(xié)議無(wú)縫支持 Dubbo3 的全部服務(wù)治理能力。

在Cloud Native的潮流下,跨平臺(tái)、跨廠商、跨環(huán)境的系統(tǒng)間互操作性的需求必然會(huì)催生基于開(kāi)放標(biāo)準(zhǔn)的RPC技術(shù),而gRPC順應(yīng)了歷史趨勢(shì),得到了越來(lái)越廣泛地應(yīng)用。在微服務(wù)領(lǐng)域,Triple協(xié)議的提出與落地,是 Dubbo3 邁向云原生微服務(wù)的一大步。

Dubbo2

Protocol SPEC


  • Magic - Magic High & Magic Low (16 bits)

    用值0xdabb標(biāo)識(shí)dubbo協(xié)議

  • Req/Res (1 bit)

    確定這是一個(gè)請(qǐng)求或響應(yīng)。請(qǐng)求-1;答復(fù)-0。

  • 2 Way (1 bit)

    僅在Req/Res為1(請(qǐng)求)時(shí)有用,無(wú)論是否從服務(wù)器返回值。如果需要從服務(wù)器返回值,請(qǐng)?jiān)O(shè)置為1。

  • Event (1 bit)

    標(biāo)識(shí)事件消息,例如心跳事件。如果這是一個(gè)事件,則設(shè)置為1。

  • Serialization ID (5 bit)
    Identifies serialization type: the value for fastjson is 6.
  • Status (8 bits)

    標(biāo)識(shí)序列化類(lèi)型:fastjson的值為6。

    • 20 - OK
    • 30 - CLIENT_TIMEOUT
    • 31 - SERVER_TIMEOUT
    • 40 - BAD_REQUEST
    • 50 - BAD_RESPONSE
    • 60 - SERVICE_NOT_FOUND
    • 70 - SERVICE_ERROR
    • 80 - SERVER_ERROR
    • 90 - CLIENT_ERROR
    • 100 - SERVER_THREADPOOL_EXHAUSTED_ERROR
  • Request ID (64 bits)
    標(biāo)識(shí)唯一的請(qǐng)求。Numeric (long).
  • Data Length (32)
    序列化后內(nèi)容(可變部分)的長(zhǎng)度,以字節(jié)計(jì)。 Numeric (integer).
  • Variable Part

    每個(gè)部分都是一個(gè)字節(jié)[],在使用特定的序列化類(lèi)型進(jìn)行序列化之后,通過(guò)序列化ID進(jìn)行標(biāo)識(shí)。

序列化后的每個(gè)部分都是一個(gè)字節(jié)[],具有特定的序列化類(lèi)型,由序列化ID標(biāo)識(shí)

  1. 如果內(nèi)容是請(qǐng)求(Req/Res=1),則每個(gè)部分由內(nèi)容組成,依次為:

    • Dubbo version
    • Service name
    • Service version
    • Method name
    • Method parameter types
    • Method arguments
    • Attachments
  2. 如果內(nèi)容是響應(yīng)(Req/Res=0),則每個(gè)部分由內(nèi)容組成,依次為:

    • 返回值類(lèi)型,標(biāo)識(shí)從服務(wù)器端返回的值類(lèi)型:RESPONSE_NULL_value-2、RESPONSE_value-1、RESPONSE_WITH_EXCEPTION-0。

    • 返回值,服務(wù)器返回的實(shí)際值。

注意: 對(duì)于(Variable Part)變長(zhǎng)部分,當(dāng)前版本的dubbo框架使用json序列化時(shí),在每部分內(nèi)容間額外增加了換行符作為分隔,請(qǐng)選手在Variable Part的每個(gè)part后額外增加換行符, 如:

Dubbo version bytes (換行符)
Service name bytes  (換行符)
...


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)