Dubbo 如何成為連接異構微服務體系的最佳服務開發框架?

Dubbo 如何成為連接異構微服務體系的最佳服務開發框架?

作者 | 劉軍

從編程開發的角度來說,Apache Dubbo (以下簡稱 Dubbo)首先是一款 RPC 服務框架,它最大的優勢在於提供了面向接口代理的服務編程模型,對開發者屏蔽了底層的遠程通信細節。同時 Dubbo 也是一款服務治理框架,它為分佈式部署的微服務提供了服務發現、流量調度等服務治理解決方案。

在這篇文章中,我們將以以上基礎能力為背景,嘗試突破 Dubbo 體系自身,探索如何利用 Dubbo 對多協議、多服務發現模型的支持,來實現異構微服務體系間的互聯互通。在實際業務場景中,這可以用來解決異構技術體系共存場景下的通信問題,幫助公司實現在異構技術體系間作平滑遷移,解決大規模跨區域、多集群部署場景的地址發現及流量調度等問題。

Dubbo 如何成为连接异构微服务体系的最佳服务开发框架?

面向接口代理的透明服務開發框架

我們還是從 Dubbo 是一個微服務開發框架 這個大家熟知的概念開始。就像 Spring 是開發 Java 應用的基礎框架一樣,我們經常會選用 Dubbo 作為開發微服務業的基礎框架。Dubbo 框架的最大優勢我認為就在其面向接口的編程模型,使得開發遠程服務調用就像開發本地服務一樣(以 Java 語言為例):

1、服務定義

<code>public interface GreetingsService {
String sayHi(String name);
}
/<code>

2、消費方調用服務

<code>// 和調用本地服務一樣,完全透明。
@Reference
private GreetingService greetingService;

public void doSayHello(String name) {
greetingService.sayHi("Hello world!");
}
/<code>

下圖是 Dubbo 的基本工作原理圖,服務提供者與服務消費者之間通過註冊中心協調地址,通過約定的協議實現數據交換。

Dubbo 如何成为连接异构微服务体系的最佳服务开发框架?

Dubbo 如何成為連接異構微服務體系的最佳服務開發框架?

同構/異構微服務體系面臨的問題

關於 Dubbo 協議本身及其服務治理相關功能細節並不是本文的重點,我們今天將從一個更高的層次,來看看公司內部構建微服務體系所面的挑戰,以及 Dubbo 能為架構選型和遷移等提供哪些解決思路。

一個公司內部的微服務可能都是基於某一個相同的服務框架開發的,比如說 Dubbo,對於這樣的架構,我們稱之為是同構的微服務體系;而有些公司的微服務可能是使用多個不同的服務框架所建設,我們稱之為異構的微服務體系,多個不同技術棧微服務體系的共存在大型組織內還是非常普遍的,造成這種局面可能有很多原因。比如,可能是遺留系統帶來的,也可能是公司正在做技術棧遷移,或者就是不同業務部門為了滿足各自特殊需求而做的獨立選型(這也意味著異構微服務體系的長期共存)。

1、異構微服務體系共存

我們很容易想到的一個挑戰是:不同的體系間通常是使用不同的 RPC 通信協議、部署獨立的註冊中心集群,面對這種多協議、多註冊中心集群的場景,要如何實現相互之間透明的地址發現和透明的 RPC 調用?如果我們什麼都不做,那麼每個微服務體系就只能感知到自己體系內的服務狀態,流量也在各自的體系內封閉。而要做到從體系 A 平滑的遷移到體系 B,或者想長期的保持公司內部多個體系的共存,則解決不同體系間的互聯互通,實現流量的透明調度將是非常重要的環節。

Dubbo 如何成为连接异构微服务体系的最佳服务开发框架?

2、Dubbo 體系內部

多協議、多註冊中心集群的問題在同構的微服務體系中也可能存在,尤其是當一個組織內部的微服務規模增長到一定量級的時候。

  • 我們可能要在不同的服務之間採用不同的通信協議,因為不同的服務面臨不同的業務場景,而這也進一步導致了數據傳輸特點的不同,我們需要分別採用更適合各類業務特點的協議。比如典型的場景:我們可能對於普通的業務服務採用 Dubbo 協議,對於和 FrontEnd 交互的服務需要 HTTP 協議,而對於需要流式數據傳輸的業務則採用 gRPC 協議等等。

  • Dubbo 體系內部另一個常出現的問題是,在大規模分佈式部署的場景下,微服務系統會做跨區域、跨註冊中心的部署,這個時候就會出現多集群間地址同步和流量調度的問題。

總結起來,不論是同構體系還是異構體系,都面臨對多協議通信、多註冊中心集群地址發現的問題。Dubbo 目前是支持多協議、多註冊中心的,可以說就是為解決我們上面分析的 Dubbo 同構體系內的場景而設計的,因此下面我們從同構體系的多協議、多註冊中心場景講起,先了解 Dubbo 多協議、多註冊中心的基本支持情況以及它們是如何工作的。而在後面的一章再進一步探索怎麼擴展這個能力來支持異構微服務體系的互聯互通。

Dubbo 如何成為連接異構微服務體系的最佳服務開發框架?

Dubbo 體系內的多協議、多註冊中心機制

我們將通過兩個場景示例,來分別具體的講一下 Dubbo 的多協議、多註冊中心機制的使用方式和工作原理。

多協議

Dubbo 如何成为连接异构微服务体系的最佳服务开发框架?

以上是使用 Dubbo 開發的一套微服務,服務間通信使用到了不同的協議,根據我們的調研發現,公司內部啟用多協議其實是非常普遍需求,具體場景在此我們暫不做解釋。

應用 B 作為服務提供者,發佈了 5 個服務,其中:

  • DemoService1 DemoService2 通過 dubbo 協議發佈

  • DemoService3 DemoService4 通過 gRPC 協議發佈

  • DemoService0 通過 dubbo 、gRPC 雙協議發佈

應用 A 作為消費者,使用 dubbo 協議消費 DemoService1 DemoService2,使用 gRPC 協議消費 DemoService0。

應用 B 作為消費者,使用 gRPC 協議消費 DemoService2 DemoService4,使用 dubbo 協議消費 DemoService0。

以下是具體的代碼配置:

1、提供端應用 B

<code><service>
<service>

<service>
<service>


<service>
/<code>

2、消費端應用 A

<code><reference>
<reference>

<reference>
/<code>

3、消費端應用C

<code><reference> <reference>

<reference>/<code>

Dubbo 多協議支持現狀

Dubbo 目前所支持的協議包括 Dubbo、REST、Thrift、gRPC、JsonRPC、Hessian 等,基本涵蓋了業界大多數主流的 RPC 通信協議。需要注意的是,這些協議的支持都是以直接集成官方 Release 實現的形式來做的,我認為這是一個很好的選擇,既保證了協議解析自身的穩定性,又能使 Dubbo 社區更專注的將更多的精力放在 Dubbo 外圍服務治理能力的改善上。試想如果 Dubbo 社區自己為每個協議提供實現,那是要花費多少精力和時間才能使每種協議達到穩定的生產可用。

除了以上官方提供支持的協議之外,得益於 Dubbo 靈活的擴展機制,想要為 Dubbo 擴展協議非常容易,開發者可以隨時為 Dubbo 增加更多的協議支持,包括自有協議擴展。

Dubbo 如何成为连接异构微服务体系的最佳服务开发框架?

多協議能解決的問題

  • 將 RPC 框架無縫地接入 Dubbo 的服務治理體系。

    通過協議擴展將 RPC 協議納入 Dubbo 服務開發體系,從而複用 Dubbo 的編程模型和服務發現、流量管控等能力。比如 gRPC,其服務治理體系相對比較弱、編程 API 不夠友好,很難直接用於微服務開發。

  • 滿足不同場景的調用需求。

    各個服務可能是為了滿足不同業務需求而開發,同時外圍消費端應用的技術棧也可能多種多樣,通過啟用不同的通信協議,可以最優化不同場景的通信需求。
  • 實現協議間的遷移。
    通過支持多種協議,藉助註冊中心的協調,可以快速滿足公司內協議遷移的需求。如從自有協議升級到 Dubbo 協議,Dubbo 協議自身升級,從 Dubbo 協議遷移到 gRPC,從 REST 遷移到 Dubbo 協議等。

多註冊中心

當服務集群規模小的時候,一箇中心化的集群部署方案能很好的解決我們的業務問題。但是隨著應用規模的增長、用戶流量的增加,我們就不得不考慮要為業務系統引入跨區域、多集群的部署方案,而此時同業務系統密切相關的註冊中心集群也面臨部署方案的選型:

1、繼續維持全局共享的註冊中心集群。這種架構方案的優點是簡單;缺點是註冊中心集群由於要保存全量的地址數據,存儲和推送壓力會變得很大,另外對於一些註冊中心產品(如 Zookeeper 等)在跨集群網絡部署的場景下穩定性和性能可能都會面臨挑戰。

2、每個業務集群部署獨立的註冊中心集群。多註冊中心集群的優點是能解決跨集群網絡可用性的問題,同時也能夠減輕註冊中心的存儲和推送壓力;缺點則是要求服務框架(如 Dubbo 等)能有同時發佈/監聽多個註冊中心集群的能力。

下面我們具體看一下,Dubbo 為多註冊中心集群場景提供的解決方案。

Dubbo 如何成为连接异构微服务体系的最佳服务开发框架?

上圖有兩個業務集群,分別部署在北京和上海,每個業務集群有自己獨立的註冊中心集群,要解決兩個業務集群間服務的透明 RPC 通信問題。

1、服務提供端,雙註冊中心發佈

<code><registry> <registry>

<service>
<service>
/<code>

2、服務消費端,根據消費需求做單/雙註冊中心訂閱

<code><registry> <registry>

<reference>

<reference>

<reference>

<reference>
/<code>

Dubbo 對異構註冊中心集群的支持

雖然我們會做多註冊中心集群部署,但通常情況下,我們部署的都是相同的註冊中心產品,如都是 Zookeeper、Nacos;而對於註冊中心遷移的場景,則要求 Dubbo 能提供對更多的註冊中心產品的支持,或者最重要的是要有很好的擴展能力。Dubbo 官方目前支持的註冊中心實現有:

Dubbo 如何成为连接异构微服务体系的最佳服务开发框架?

這裡需要特別提到的一點是,當前 Dubbo 的服務註冊/發現模型是以接口為粒度的,而從 2.7.5 版本開始,Dubbo 新引入了應用粒度的服務註冊/發現模型。這一方面有助於優化 Dubbo 當前服務發現機制、提升服務容量,另一方面對於聯通以 SpringCloud 為代表的微服務體系也非常重要(關於這點在下一章中有進一步提及)。更多關於《應用粒度服務發現:服務自省》的介紹,我們將在接下來的文章或文檔中予以補充,請持續關注。

多訂閱帶來的流量調度問題

在引入多註冊中心集群后,Dubbo 在流量選址時的多了一層註冊中心集群間的負載均衡:

Dubbo 如何成为连接异构微服务体系的最佳服务开发框架?

在 Cluster Invoker 這一級,我們支持的選址策略有(2.7.5+ 版本,具體使用請參見文檔):

1、指定優先級

<code>
<registry>
/<code>

2、同 zone 優先

<code>
<registry>
/<code>

3、權重輪選

<code>
<registry>
<registry>/<code>

4、默認,stick to 任意可用

多註冊中心適用的場景

  • 同區域流量優先調度
    出於容災或者服務伸縮性需求,服務/應用往往需要部署在多個獨立的機房/區域,在每個區域有獨立註冊中心集群的場景下,實現同區域的流量優先調度就能很好的解決延遲和可用性問題。
  • 註冊中心遷移
    公司的服務一直以來可能是存儲在某一個註冊中心,如 Zookeeper,但到了某個時間節點,因為各種各樣的原因,當我們要遷移到另外的註冊中心時,多註冊中心模型能夠保證平滑的遷移。
  • 異構系統互通
    不同微服務體系開發的服務,都封閉在各自的服務發現體系中,而通過統一的多註冊中心模型,可以實現不同體系的服務互相發現。

Dubbo 如何成為連接異構微服務體系的最佳服務開發框架?

藉助 Dubbo 聯通異構的微服務體系

上文我們提到了在組織內存在異構微服務體系的各種合理可能性,現在我們來具體看一下異構微服務體系的實際場景,以及使用 Dubbo 實現互聯互通的解決方法。首先我們先通過一張圖來看一下,聯通異構的微服務體系具體是一個什麼樣的場景。

Dubbo 如何成为连接异构微服务体系的最佳服务开发框架?

如上圖所示,我們有部分微服務可以是基於 SpringCloud、gRPC、K8S 或者是自建體系構建的,他們各自之間默認是相互隔離無法聯通的。當我們再構建一套基於 Dubbo 的微服務體系時,則利用 Dubbo 的多協議、多服務發現模型,我們就可以做到和各個微服務體系間的兩兩之間的互聯互通。進一步的,如圖中橙色箭頭所示,依賴 Dubbo 體系作為橋接層,我們還可以實現兩個異構微服務體系間的打通。

對於以下幾個示例場景,由於在地址發現層面目前沒有統一的標準,我們暫且假設地址發現層面不同的體系建是沒有障礙的,我們將重點關注遷移的基本流程以及通信協議環節。(關於地址發現部分,我們將在後續《服務自省:基於應用粒度的服務發現》之後再深入探討)

Dubbo 體系內的協議遷移(共存)

絕大多數開發者對 Dubbo 有這麼一個固有認知:使用 Dubbo 開發微服務系統,則就要用 Dubbo 協議來作為服務間的通信協議才是最優方案。實際上,我們完全沒有必要只束縛在 Dubbo RPC 協議上。Dubbo 作為微服務開發框架和 Dubbo 作為 RPC 協議這是兩個概念,其實是完全可以分開來看待的,比如我們用 Dubbo 框架開發的業務系統,選用 rest、gRPC 通信是完全沒有問題的(參加 Dubbo 支持的協議列表),具體用什麼協議根據業務特點和技術規劃才是最適合的。

Dubbo 如何成为连接异构微服务体系的最佳服务开发框架?

當前在雲原生、Mesh 的大背景下, HTTP1/2、gRPC 協議開始受到越來越多的關注,一方面原因自然是因為它們在標準化方面做的更好,得到的更多的網絡設備和基礎設施的支持,具備更好的通用性和穿透性。對於很多有云原生遷移意願的企業來說,往此類協議遷移無疑將對之後的架構升級有更多的幫助。

下圖演示了在 Dubbo 體系內,從 Dubbo 協議向 gRPC 協議遷移的一箇中間狀態。

Dubbo 如何成为连接异构微服务体系的最佳服务开发框架?
  • 最左邊的代表尚未遷移的老應用,這類應用在遷移過程中仍然要消費和提供 Dubbo 協議的服務。

  • 中間的代表處於遷移中的應用,他們中間可能有些是服務提供者,既要為左邊的老系統提供提供 Dubbo 協議服務;又要為右邊的新系統提供 gRPC 服務;因此他們都是雙協議暴露服務。

  • 最右邊則代表是新開發的或者已經遷移完成的應用,這個體系內已能完全用 gRPC 協議通信。

  • 最終度過中間態後,我們期望所有的應用都達到最左邊應用的狀態,實現完全的 gRPC 協議通信。

Spring Cloud 體系遷移到 Dubbo 體系(共存)

如前文所述,由於 SpringCloud 和 Dubbo 間服務發現模型的問題,要兩個體系間的地址互通需要 Dubbo 側作相應的適配,關於這部分內容將在接下來的 2.7.5 版本《服務自省》部分發布,在此我們暫且認為已經打通。

Dubbo 如何成为连接异构微服务体系的最佳服务开发框架?

Dubbo 體系內的部分應用作為透明的聯通兩個體系的關鍵節點,部分服務提供者應用要雙協議發佈、部分消費者應用要做到選定協議消費。由於老的 Spring Cloud 體系不允許做任何改動,因此聯通兩套體系的關鍵是 REST 協議,對 Dubbo 側的應用來說:

  • 部分應用可能要以 REST 協議消費 SpringCloud 的服務;

  • 部分應用可能要暴露 REST 協議共 SpringCloud 消費;

  • Dubbo 自有體系內則通過自己選定的協議通信,這裡就比較靈活了,可以是 Dubbo、REST、gRPC 等其中的任一種。而如果選定 REST 協議則對於與 SpringCloud 體系的聯通就變得更加自然了,因為兩端的協議都是統一的。

對於消費 Spring Cloud 服務的應用,要配置服務 :

<code><reference>
/<code>

對於提供服務給 Spring Cloud 側消費的應用,則指定服務暴露為 rest 協議,或者雙協議暴露(因如果這個服務還要被新體系內的應用調用到):

<code><service>
/<code>

作為 Dubbo 的維護者,雖然我們這裡有明顯的偏向性,講的是從如何從 SpringCloud 體系遷移到 Dubbo 體系。但是反過來考慮,如果你已經或者即將選型 Dubbo 來開發微服務,則未來從 Dubbo 遷移到 SpringCloud 也是同樣的思路,Dubbo 的多協議、多註冊模型為雙向遷移都提供了同樣的靈活性。

自建體系遷移到 Dubbo 體系(共存)

這個場景和上一節中講到的的 SpringCloud 遷移有些類似,最大的區別在於 rest 協議是 Dubbo 官方默認提供支持的,而對於已有的微服務體系內的私有通信協議,則需要先要自己去擴展 Dubbo Protocol 來提供協議層面的支持,關於 Protocol 如何擴展請參見以下官方文檔:

http://dubbo.apache.org/zh-cn/docs/dev/impls/protocol.html

Dubbo 如何成為連接異構微服務體系的最佳服務開發框架?

總結與展望

要實現異構微服務體系間的共存或遷移,關鍵點在打通異構體系間的協議與服務發現,得益於 Dubbo 自身對多協議、多註冊模型的支持,我們可以很容易的使 Dubbo 成為橋接異構微服務體系的中間層。熟悉 Dubbo 多協議實現細節的同學,可能會擔心在服務數量較多的場景下,多協議註冊會導致地址數量翻倍從而影響地址推送性能。

另外,在本文“藉助 Dubbo 聯通異構的微服務體系”一節中,關於如何實現異構體系間的透明服務發現部分,我們沒有做詳細的說明。涉及服務發現的這部分,我們將在接下來的文章中做具體闡述,看看 Dubbo 2.7.5 版本引入新的服務發現機制是如何解決這個問題的,請持續關注後續文章及 Dubbo 官方文檔。

作者:劉軍,GitHub賬號Chickenlj,Apache Dubbo PMC,項目核心維護者,見證了Dubbo從重啟開源到Apache畢業的整個流程。現任職阿里云云原生應用平臺團隊,參與服務框架、微服務相關工作,目前主要在推動Dubbo開源的雲原生化。

本文縮略圖:icon by Dora1900


分享到:


相關文章: