本文我們將介紹 Apache Dubbo 靈活的多協議設計原則,基于這一設計,在 Dubbo 框架底層可靈活的選用 HTTP/2、HTTP/REST、TCP、gRPC、JsonRPC、Hessian2 等任一 RPC 通信協議,同時享用統一的 API 與對等的服務治理能力。同時,我們還介紹了 Dubbo 的單端口多協議能力,也就是在單個端口同時監聽、處理多個協議,這對于簡化多協議同時發布的場景非常有用。
不綁定 RPC 協議的設計原則
Aliware
Dubbo 框架不綁定任何通信協議,你可以根據業務場景選擇 HTTP/2 通信協議,也可以選用 HTTP/REST、TCP(Dubbo2)、gRPC、JsonRPC、Hessian2 等官方支持的通信協議,如果以上協議都不能滿足需求,還可以非常方便的通過定制方式接入自定義協議。如果你想在一個應用內使用多個協議,也可以非常容易的做到,比如一個接口使用 HTTP/2 通信,另一個接口使用 TCP 通信,一個應用內發布或調用多個使用不同協議的服務。

通過 Dubbo 框架的多協議支持,你可以做到:
- 將任意通信協議無縫地接入 Dubbo 服務治理體系。Dubbo 體系下的所有通信協議,都可以享受到 Dubbo 的編程模型、服務發現、流量管控等優勢。比如 gRPC over Dubbo 的模式,服務治理、編程 API 都能夠零成本接入 Dubbo 體系。
- 兼容不同技術棧,業務系統混合使用不同的服務框架、RPC 框架。比如有些服務使用 gRPC 或者 Spring Cloud 開發,有些服務使用 Dubbo 框架開發,通過 Dubbo 的多協議支持可以很好的實現互通。
- 讓協議遷移變的更簡單。通過多協議、注冊中心的協調,可以快速滿足公司內協議遷移的需求。比如如從自研協議升級到 Dubbo 協議,Dubbo 協議自身升級,從 Dubbo 協議遷移到 gRPC,從 HTTP 遷移到 Dubbo 協議等。
官方接入的主流協議
Aliware
HTTP/2 (Triple)
Triple 協議是 Dubbo3 發布的面向云原生時代的通信協議,它基于 HTTP/2 并且完全兼容 gRPC 協議,原生支持 Streaming 通信語義,自 Triple 協議開始,Dubbo 還支持基于 Protobuf 的服務定義與數據傳輸。Triple 具備更好的網關、代理穿透性,因此非常適合于跨網關、代理通信的部署架構,如服務網格等。
Triple 協議的核心特性如下:
- 支持 TLS 加密、Plaintext 明文數據傳輸
- 支持反壓與限流
- 支持 Streaming 流式通信
在編程與通信模型上,Triple 協議支持如下模式:
- 消費端異步請求(Client Side Asynchronous Request-Response)
- 提供端異步執行(Server Side Asynchronous Request-Response)
- 消費端請求流(Request Streaming)
- 提供端響應流(Response Streaming)
- 雙向流式通信(Bidirectional Streaming)
TCP (Dubbo2)
Dubbo2 協議是基于 TCP 傳輸層協議之上構建的一套 RPC 通信協議,由于其緊湊、靈活、高性能的特點,在 Dubbo2 時代取得了非常廣泛的應用,是企業構建高性能、大規模微服務集群的關鍵通信方案。在云原生時代,我們更推薦使用通用性、穿透性更好的 Triple 協議。
gRPC
你可以用 Dubbo 開發和治理微服務,然后設置使用 gRPC 協議進行底層通信。但為什么要這么做那,與直接使用 gRPC 框架對比有什么優勢?簡單的答案是,這是使用 gRPC 進行微服務開發的常用模式,具體請往下看。
gRPC 是谷歌開源的基于 HTTP/2 的通信協議,如同我們在產品對比[1]文檔中提到的,gRPC 的定位是通信協議與實現,是一款純粹的 RPC 框架,而 Dubbo 定位是一款微服務框架,為微服務實踐提供解決方案。因此,相比于 Dubbo,gRPC 相對欠缺了微服務編程模型、服務治理等能力的抽象。
在 Dubbo 體系下使用 gRPC 協議 (gRPC over Dubbo Framework) 是一個非常高效和輕量的選擇,它讓你既能使用原生的 gRPC 協議通信,又避免了基于 gRPC 進行二次定制與開發的復雜度 (二次開發與定制 gRPC,是很多企業規模化實踐后證實不可避免的環節,Dubbo 框架替開發者完成了這一步,讓開發者可以直接以最簡單的方式使用 gRPC)。
REST
微服務領域常用的一種通信模式是 HTTP + JSON,包括 Spring Cloud、Microprofile 等一些主流的微服務框架都默認使用的這種通信模式,Dubbo 同樣提供了對基于 HTTP 的編程、通信模式的支持。
其他通信協議
除了以上介紹的幾種協議之外,你還可以將以下協議運行在 Dubbo 之上。對 Dubbo 而言,只需要修改一行簡單的配置,就可以切換底層服務的通信協議,其他外圍 API 和治理能力不受影響。
- Hessian2
- Thrift
- JsonRPC
單端口多協議
Aliware
自 Dubbo 3.2 版本開始,Dubbo 提供了單個端口上的協議復用能力,通過調整 Protocol 配置即可實現。
比如在開啟 HTTP/2 (Triple) 協議 或 gRPC 協議后,如我們同時啟動端口復用,還可以在相同的端口上為服務增加 TCP (Dubbo2) 協議、Qos 協議的支持。這些所有流量的入口都在一個統一 port 端口, Dubbo 框架負責在端口之上識別不同的 RPC 協議,并進行處理器分發,從而實現單個端口上的協議復用。
對于需要處理多個協議的場景,端口復用非常有價值。它可以用于服務的協議遷移,并且可以節約端口以及相關的資源,減少運維的復雜性等。
實現原理
以下是端口復用實現的原理圖

- 在服務的創建階段,通過從 Config 層獲取到服務導出的協議配置從而創建不同的 Protocol 對象進行導出。在導出的過程中,如果不是第一次創建端口復用的 Server,那么 Exchanger 會將 Protcol 層傳遞的數據保存到 Server,用于后續處理該協議類型的消息。
- 當客戶端的消息傳遞過來后,首先會通過 Server 傳遞給 ProtocolDetector,如果完成了識別,那么就會標記該客戶端為對應的協議。并通過 WireProtocol 配置對應的處理邏輯,最后交給 ChannelOperator 完成底層的 IO 框架和對應的 Dubbo 框架的處理邏輯的綁定。
- 以上的協議識別完成之后,Channel 已經確定了如何處理遠程的客戶端消息,通過對應的 ServerPipeline 進行處理即可(在處理的過程中也會根據配置信息決定消息的處理線程)。
使用場景
以下是幾種常見的使用場景。
- 最常用的是用于服務發現。這允許應用程序通過網絡發現服務,然后使用同一端口與它們通信,有助于降低網絡通信的復雜性,并使其更易于管理。
- 可以用于負載平衡。這允許應用程序在多個遠程服務或服務集群之間平衡負載,有助于提高服務的可擴展性、可靠性和可用性。
- 可以用于服務監控。這允許應用程序監視遠程服務的運行狀況,并在服務出現故障或變得不可用時發出警報,有助于確保服務的可用性并減少停機時間。
參考用例:
https://Github.com/apache/dubbo-samples/tree/master/dubbo-samples-port-unification
使用方式
在同一主機上部署多個服務或需要通過負載均衡器訪問多個服務。
關于 Dubbo 支持的配置方式 配置說明[2]
服務多協議導出
ext-protocol 參數支持配置多個不同的協議,協議之間通過","進行分隔。
xml 配置
<dubbo:protocol name="dubbo" port="-1" ext-protocol="tri,"/>
<bean id="greetingService" class="org.apache.dubbo.demo.provider.GreetingServiceImpl"/>
<dubbo:service delay="5000" version="1.0.0" group="greeting" timeout="5000" interface="org.apache.dubbo.demo.GreetingService" ref="greetingService" protocol="dubbo"/>
API 配置
ProtocolConfig config = new ProtocolConfig(CommonConstants.TRIPLE, -1);
config.setExtProtocol(CommonConstants.DUBBO+",");
yaml 配置
dubbo:
Application:
name: dubbo-springboot-demo-provider
protocol:
name: tri
port: -1
ext-protocol: dubbo,
properties 配置
dubbo.protocol.name=tri
dubbo.protocol.ext-protocol=dubbo,
dubbo.protocol.port=20880
Qos 接入
Qos 模塊導入
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-qos</artifactId>
</dependency>
完成 Qos 模塊的導入之后,相關的配置項可參考 Qos 操作手冊[3]進行配置。
默認情況下,基于端口復用的 Qos 服務在模塊導入后是啟動的。
Qos 使用
將 Qos 協議接入到端口復用的場景下,需要在建立連接之后,客戶端先向服務端發送消息,對比將 Qos 協議通過單個端口提供服務,端口復用版的 Qos 協議在處理 te.NET 連接的情況下需要用戶執行一些操作,完成協議識別(二選一)。
- 直接調用命令
直接調用 telnet 支持的命令也可以完成識別,在用戶不熟悉的情況下可以調用 help 指令完成識別

2. 發送 telnet 命令識別
通過 telnet 命令建立連接之后,執行以下幾個步驟:
-
- 使用 crtl + "]" 進入到 telnet 交互界面(telnet 默認的 escape character)
- 調用 "send ayt" 向服務端發送特殊識別字段(為 telnet 協議的一個特殊字段)
- 回車完成消息發送并進入到 dubbo 的交互界面

服務引用
以
dubbo-samples-port-unification[4]中的例子作為基礎, 引用不同協議的服務和非端口復用情況下的配置是一致的,下面通過 Consumer 端的 InvokerListener 輸出調用過程中的 URL 信息。
ReferenceConfig<GreetingService> reference = new ReferenceConfig<>();
reference.setInterface(GreetingService.class);
reference.setListener("consumer");
reference.setProtocol(this.protocol);
// reference.setProtocol(CommonConstants.DUBBO);
// reference.setProtocol(CommonConstants.TRIPLE);
總結
Aliware
對于微服務實踐中經常會遇到的多協議通信的場景,Dubbo 不綁定協議的設計讓用戶可以靈活的選擇通信協議,整個協議選擇過程對上層 API 編碼與運維治理完全透明;對于要在一個集群內同時處理多個協議的場景,Dubbo 的多協議支持也可以從容應對,而單端口的多協議復用支持進一步簡化了這一過程。
在接下來的一篇文章中,我們將詳細介紹如何在 Dubbo 框架中開發 gRPC 協議通信的服務,極大的簡化了 gRPC 微服務開發成本,避免了二次開發,為原生 gRPC 提供了統一的編程 API 與開箱即用的服務治理能力。
相關鏈接:
[1]產品對比
https://cn.dubbo.apache.org/zh-cn/overview/what/xyz-difference/
[2]配置說明
https://cn.dubbo.apache.org/zh-cn/overview/mannual/JAVA-sdk/reference-manual/config/
[3]Qos 操作手冊
https://cn.dubbo.apache.org/zh-cn/overview/mannual/java-sdk/reference-manual/qos/overview/
[4]dubbo-samples-port-unification
https://github.com/apache/dubbo-samples/tree/master/3-extensions/protocol/dubbo-samples-port-unification
作者:華鐘明
來源:微信公眾號:阿里巴巴中間件
出處
:https://mp.weixin.qq.com/s/3Qr6diH6WJSwv8HIma7-eA