本文我們將介紹 Apache Dubbo 靈活的多協(xié)議設(shè)計(jì)原則,基于這一設(shè)計(jì),在 Dubbo 框架底層可靈活的選用 HTTP/2、HTTP/REST、TCP、gRPC、JsonRPC、Hessian2 等任一 RPC 通信協(xié)議,同時(shí)享用統(tǒng)一的 API 與對(duì)等的服務(wù)治理能力。同時(shí),我們還介紹了 Dubbo 的單端口多協(xié)議能力,也就是在單個(gè)端口同時(shí)監(jiān)聽、處理多個(gè)協(xié)議,這對(duì)于簡(jiǎn)化多協(xié)議同時(shí)發(fā)布的場(chǎng)景非常有用。
不綁定 RPC 協(xié)議的設(shè)計(jì)原則
Aliware
Dubbo 框架不綁定任何通信協(xié)議,你可以根據(jù)業(yè)務(wù)場(chǎng)景選擇 HTTP/2 通信協(xié)議,也可以選用 HTTP/REST、TCP(Dubbo2)、gRPC、JsonRPC、Hessian2 等官方支持的通信協(xié)議,如果以上協(xié)議都不能滿足需求,還可以非常方便的通過定制方式接入自定義協(xié)議。如果你想在一個(gè)應(yīng)用內(nèi)使用多個(gè)協(xié)議,也可以非常容易的做到,比如一個(gè)接口使用 HTTP/2 通信,另一個(gè)接口使用 TCP 通信,一個(gè)應(yīng)用內(nèi)發(fā)布或調(diào)用多個(gè)使用不同協(xié)議的服務(wù)。
通過 Dubbo 框架的多協(xié)議支持,你可以做到:
- 將任意通信協(xié)議無縫地接入 Dubbo 服務(wù)治理體系。Dubbo 體系下的所有通信協(xié)議,都可以享受到 Dubbo 的編程模型、服務(wù)發(fā)現(xiàn)、流量管控等優(yōu)勢(shì)。比如 gRPC over Dubbo 的模式,服務(wù)治理、編程 API 都能夠零成本接入 Dubbo 體系。
- 兼容不同技術(shù)棧,業(yè)務(wù)系統(tǒng)混合使用不同的服務(wù)框架、RPC 框架。比如有些服務(wù)使用 gRPC 或者 Spring Cloud 開發(fā),有些服務(wù)使用 Dubbo 框架開發(fā),通過 Dubbo 的多協(xié)議支持可以很好的實(shí)現(xiàn)互通。
- 讓協(xié)議遷移變的更簡(jiǎn)單。通過多協(xié)議、注冊(cè)中心的協(xié)調(diào),可以快速滿足公司內(nèi)協(xié)議遷移的需求。比如如從自研協(xié)議升級(jí)到 Dubbo 協(xié)議,Dubbo 協(xié)議自身升級(jí),從 Dubbo 協(xié)議遷移到 gRPC,從 HTTP 遷移到 Dubbo 協(xié)議等。
官方接入的主流協(xié)議
Aliware
HTTP/2 (Triple)
Triple 協(xié)議是 Dubbo3 發(fā)布的面向云原生時(shí)代的通信協(xié)議,它基于 HTTP/2 并且完全兼容 gRPC 協(xié)議,原生支持 Streaming 通信語義,自 Triple 協(xié)議開始,Dubbo 還支持基于 Protobuf 的服務(wù)定義與數(shù)據(jù)傳輸。Triple 具備更好的網(wǎng)關(guān)、代理穿透性,因此非常適合于跨網(wǎng)關(guān)、代理通信的部署架構(gòu),如服務(wù)網(wǎng)格等。
Triple 協(xié)議的核心特性如下:
- 支持 TLS 加密、Plaintext 明文數(shù)據(jù)傳輸
- 支持反壓與限流
- 支持 Streaming 流式通信
在編程與通信模型上,Triple 協(xié)議支持如下模式:
- 消費(fèi)端異步請(qǐng)求(Client Side Asynchronous Request-Response)
- 提供端異步執(zhí)行(Server Side Asynchronous Request-Response)
- 消費(fèi)端請(qǐng)求流(Request Streaming)
- 提供端響應(yīng)流(Response Streaming)
- 雙向流式通信(Bidirectional Streaming)
TCP (Dubbo2)
Dubbo2 協(xié)議是基于 TCP 傳輸層協(xié)議之上構(gòu)建的一套 RPC 通信協(xié)議,由于其緊湊、靈活、高性能的特點(diǎn),在 Dubbo2 時(shí)代取得了非常廣泛的應(yīng)用,是企業(yè)構(gòu)建高性能、大規(guī)模微服務(wù)集群的關(guān)鍵通信方案。在云原生時(shí)代,我們更推薦使用通用性、穿透性更好的 Triple 協(xié)議。
gRPC
你可以用 Dubbo 開發(fā)和治理微服務(wù),然后設(shè)置使用 gRPC 協(xié)議進(jìn)行底層通信。但為什么要這么做那,與直接使用 gRPC 框架對(duì)比有什么優(yōu)勢(shì)?簡(jiǎn)單的答案是,這是使用 gRPC 進(jìn)行微服務(wù)開發(fā)的常用模式,具體請(qǐng)往下看。
gRPC 是谷歌開源的基于 HTTP/2 的通信協(xié)議,如同我們?cè)?strong>產(chǎn)品對(duì)比[1]文檔中提到的,gRPC 的定位是通信協(xié)議與實(shí)現(xiàn),是一款純粹的 RPC 框架,而 Dubbo 定位是一款微服務(wù)框架,為微服務(wù)實(shí)踐提供解決方案。因此,相比于 Dubbo,gRPC 相對(duì)欠缺了微服務(wù)編程模型、服務(wù)治理等能力的抽象。
在 Dubbo 體系下使用 gRPC 協(xié)議 (gRPC over Dubbo Framework) 是一個(gè)非常高效和輕量的選擇,它讓你既能使用原生的 gRPC 協(xié)議通信,又避免了基于 gRPC 進(jìn)行二次定制與開發(fā)的復(fù)雜度 (二次開發(fā)與定制 gRPC,是很多企業(yè)規(guī)模化實(shí)踐后證實(shí)不可避免的環(huán)節(jié),Dubbo 框架替開發(fā)者完成了這一步,讓開發(fā)者可以直接以最簡(jiǎn)單的方式使用 gRPC)。
REST
微服務(wù)領(lǐng)域常用的一種通信模式是 HTTP + JSON,包括 Spring Cloud、Microprofile 等一些主流的微服務(wù)框架都默認(rèn)使用的這種通信模式,Dubbo 同樣提供了對(duì)基于 HTTP 的編程、通信模式的支持。
其他通信協(xié)議
除了以上介紹的幾種協(xié)議之外,你還可以將以下協(xié)議運(yùn)行在 Dubbo 之上。對(duì) Dubbo 而言,只需要修改一行簡(jiǎn)單的配置,就可以切換底層服務(wù)的通信協(xié)議,其他外圍 API 和治理能力不受影響。
- Hessian2
- Thrift
- JsonRPC
單端口多協(xié)議
Aliware
自 Dubbo 3.2 版本開始,Dubbo 提供了單個(gè)端口上的協(xié)議復(fù)用能力,通過調(diào)整 Protocol 配置即可實(shí)現(xiàn)。
比如在開啟 HTTP/2 (Triple) 協(xié)議 或 gRPC 協(xié)議后,如我們同時(shí)啟動(dòng)端口復(fù)用,還可以在相同的端口上為服務(wù)增加 TCP (Dubbo2) 協(xié)議、Qos 協(xié)議的支持。這些所有流量的入口都在一個(gè)統(tǒng)一 port 端口, Dubbo 框架負(fù)責(zé)在端口之上識(shí)別不同的 RPC 協(xié)議,并進(jìn)行處理器分發(fā),從而實(shí)現(xiàn)單個(gè)端口上的協(xié)議復(fù)用。
對(duì)于需要處理多個(gè)協(xié)議的場(chǎng)景,端口復(fù)用非常有價(jià)值。它可以用于服務(wù)的協(xié)議遷移,并且可以節(jié)約端口以及相關(guān)的資源,減少運(yùn)維的復(fù)雜性等。
實(shí)現(xiàn)原理
以下是端口復(fù)用實(shí)現(xiàn)的原理圖
- 在服務(wù)的創(chuàng)建階段,通過從 Config 層獲取到服務(wù)導(dǎo)出的協(xié)議配置從而創(chuàng)建不同的 Protocol 對(duì)象進(jìn)行導(dǎo)出。在導(dǎo)出的過程中,如果不是第一次創(chuàng)建端口復(fù)用的 Server,那么 Exchanger 會(huì)將 Protcol 層傳遞的數(shù)據(jù)保存到 Server,用于后續(xù)處理該協(xié)議類型的消息。
- 當(dāng)客戶端的消息傳遞過來后,首先會(huì)通過 Server 傳遞給 ProtocolDetector,如果完成了識(shí)別,那么就會(huì)標(biāo)記該客戶端為對(duì)應(yīng)的協(xié)議。并通過 WireProtocol 配置對(duì)應(yīng)的處理邏輯,最后交給 ChannelOperator 完成底層的 IO 框架和對(duì)應(yīng)的 Dubbo 框架的處理邏輯的綁定。
- 以上的協(xié)議識(shí)別完成之后,Channel 已經(jīng)確定了如何處理遠(yuǎn)程的客戶端消息,通過對(duì)應(yīng)的 ServerPipeline 進(jìn)行處理即可(在處理的過程中也會(huì)根據(jù)配置信息決定消息的處理線程)。
使用場(chǎng)景
以下是幾種常見的使用場(chǎng)景。
- 最常用的是用于服務(wù)發(fā)現(xiàn)。這允許應(yīng)用程序通過網(wǎng)絡(luò)發(fā)現(xiàn)服務(wù),然后使用同一端口與它們通信,有助于降低網(wǎng)絡(luò)通信的復(fù)雜性,并使其更易于管理。
- 可以用于負(fù)載平衡。這允許應(yīng)用程序在多個(gè)遠(yuǎn)程服務(wù)或服務(wù)集群之間平衡負(fù)載,有助于提高服務(wù)的可擴(kuò)展性、可靠性和可用性。
- 可以用于服務(wù)監(jiān)控。這允許應(yīng)用程序監(jiān)視遠(yuǎn)程服務(wù)的運(yùn)行狀況,并在服務(wù)出現(xiàn)故障或變得不可用時(shí)發(fā)出警報(bào),有助于確保服務(wù)的可用性并減少停機(jī)時(shí)間。
參考用例:
https://Github.com/apache/dubbo-samples/tree/master/dubbo-samples-port-unification
使用方式
在同一主機(jī)上部署多個(gè)服務(wù)或需要通過負(fù)載均衡器訪問多個(gè)服務(wù)。
關(guān)于 Dubbo 支持的配置方式 配置說明[2]
服務(wù)多協(xié)議導(dǎo)出
ext-protocol 參數(shù)支持配置多個(gè)不同的協(xié)議,協(xié)議之間通過","進(jìn)行分隔。
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 模塊導(dǎo)入
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-qos</artifactId>
</dependency>
完成 Qos 模塊的導(dǎo)入之后,相關(guān)的配置項(xiàng)可參考 Qos 操作手冊(cè)[3]進(jìn)行配置。
默認(rèn)情況下,基于端口復(fù)用的 Qos 服務(wù)在模塊導(dǎo)入后是啟動(dòng)的。
Qos 使用
將 Qos 協(xié)議接入到端口復(fù)用的場(chǎng)景下,需要在建立連接之后,客戶端先向服務(wù)端發(fā)送消息,對(duì)比將 Qos 協(xié)議通過單個(gè)端口提供服務(wù),端口復(fù)用版的 Qos 協(xié)議在處理 te.NET 連接的情況下需要用戶執(zhí)行一些操作,完成協(xié)議識(shí)別(二選一)。
- 直接調(diào)用命令
直接調(diào)用 telnet 支持的命令也可以完成識(shí)別,在用戶不熟悉的情況下可以調(diào)用 help 指令完成識(shí)別
2. 發(fā)送 telnet 命令識(shí)別
通過 telnet 命令建立連接之后,執(zhí)行以下幾個(gè)步驟:
-
- 使用 crtl + "]" 進(jìn)入到 telnet 交互界面(telnet 默認(rèn)的 escape character)
- 調(diào)用 "send ayt" 向服務(wù)端發(fā)送特殊識(shí)別字段(為 telnet 協(xié)議的一個(gè)特殊字段)
- 回車完成消息發(fā)送并進(jìn)入到 dubbo 的交互界面
服務(wù)引用
以
dubbo-samples-port-unification[4]中的例子作為基礎(chǔ), 引用不同協(xié)議的服務(wù)和非端口復(fù)用情況下的配置是一致的,下面通過 Consumer 端的 InvokerListener 輸出調(diào)用過程中的 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);
總結(jié)
Aliware
對(duì)于微服務(wù)實(shí)踐中經(jīng)常會(huì)遇到的多協(xié)議通信的場(chǎng)景,Dubbo 不綁定協(xié)議的設(shè)計(jì)讓用戶可以靈活的選擇通信協(xié)議,整個(gè)協(xié)議選擇過程對(duì)上層 API 編碼與運(yùn)維治理完全透明;對(duì)于要在一個(gè)集群內(nèi)同時(shí)處理多個(gè)協(xié)議的場(chǎng)景,Dubbo 的多協(xié)議支持也可以從容應(yīng)對(duì),而單端口的多協(xié)議復(fù)用支持進(jìn)一步簡(jiǎn)化了這一過程。
在接下來的一篇文章中,我們將詳細(xì)介紹如何在 Dubbo 框架中開發(fā) gRPC 協(xié)議通信的服務(wù),極大的簡(jiǎn)化了 gRPC 微服務(wù)開發(fā)成本,避免了二次開發(fā),為原生 gRPC 提供了統(tǒng)一的編程 API 與開箱即用的服務(wù)治理能力。
相關(guān)鏈接:
[1]產(chǎn)品對(duì)比
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 操作手冊(cè)
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
作者:華鐘明
來源:微信公眾號(hào):阿里巴巴中間件
出處
:https://mp.weixin.qq.com/s/3Qr6diH6WJSwv8HIma7-eA