從編程開發的角度來說,Apache Dubbo (以下簡稱 Dubbo )首先是一款 RPC 服務框架,它最大的優勢在于提供了面向接口代理的服務編程模型,對開發者屏蔽了底層的遠程通信細節。同時 Dubbo 也是一款服務治理框架,它為分布式部署的微服務提供了服務發現、流量調度等服務治理解決方案。
在這篇文章中,我們將以以上基礎能力為背景,嘗試突破 Dubbo 體系自身,探索如何利用 Dubbo 對多協議、多服務發現模型的支持,來實現異構微服務體系間的互聯互通。在實際業務場景中,這可以用來解決異構技術體系共存場景下的通信問題,幫助公司實現在異構技術體系間作平滑遷移,解決大規模跨區域、多集群部署場景的地址發現及流量調度等問題。
面向接口代理的透明服務開發框架
我們還是從 Dubbo 是一個微服務開發框架 這個大家熟知的概念開始。就像 Spring 是開發 Java 應用的基礎框架一樣,我們經常會選用 Dubbo 作為開發微服務業的基礎框架。 Dubbo 框架的最大優勢我認為就在其面向接口的編程模型,使得開發遠程服務調用就像開發本地服務一樣(以 Java 語言為例):
服務定義
public?interface?GreetingsService?{ ????String?sayHi(String?name); }
消費方調用服務
//?和調用本地服務一樣,完全透明。 @Reference private?GreetingService?greetingService; public?void?doSayHello(String?name)?{ ??greetingService.sayHi("Hello?world!"); }
下圖是 Dubbo 的基本工作原理圖,服務提供者與服務消費者之間通過注冊中心協調地址,通過約定的協議實現數據交換。
同構/異構微服務體系面臨的問題
關于 Dubbo 協議本身及其服務治理相關功能細節并不是本文的重點,我們今天將從一個更高的層次,來看看公司內部構建微服務體系所面的挑戰,以及 Dubbo 能為架構選型和遷移等提供哪些解決思路。
一個公司內部的微服務可能都是基于某一個相同的服務框架開發的,比如說 Dubbo,對于這樣的架構,我們稱之為是同構的微服務體系;而有些公司的微服務可能是使用多個不同的服務框架所建設,我們稱之為異構的微服務體系,多個不同技術棧微服務體系的共存在大型組織內還是非常普遍的,造成這種局面可能有很多原因。比如,可能是遺留系統帶來的,也可能是公司正在做技術棧遷移,或者就是不同業務部門為了滿足各自特殊需求而做的獨立選型(這也意味著異構微服務體系的長期共存)。
1. 異構微服務體系共存
我們很容易想到的一個挑戰是:不同的體系間通常是使用不同的 RPC 通信協議、部署獨立的注冊中心集群,面對這種多協議、多注冊中心集群的場景,要如何實現相互之間透明的地址發現和透明的 RPC 調用?如果我們什么都不做,那么每個微服務體系就只能感知到自己體系內的服務狀態,流量也在各自的體系內封閉。而要做到從體系 A 平滑的遷移到體系 B,或者想長期的保持公司內部多個體系的共存,則解決不同體系間的互聯互通,實現流量的透明調度將是非常重要的環節。
2. Dubbo 體系內部
多協議、多注冊中心集群的問題在同構的微服務體系中也可能存在,尤其是當一個組織內部的微服務規模增長到一定量級的時候。
我們可能要在不同的服務之間采用不同的通信協議,因為不同的服務面臨不同的業務場景,而這也進一步導致了數據傳輸特點的不同,我們需要分別采用更適合各類業務特點的協議。比如典型的場景:我們可能對于普通的業務服務采用 Dubbo 協議,對于和 FrontEnd 交互的服務需要 HTTP 協議,而對于需要流式數據傳輸的業務則采用 gRPC 協議等等。
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。
以下是具體的代碼配置:
提供端應用 B
消費端應用 A
消費端應用 C
Dubbo 多協議支持現狀
Dubbo 目前所支持的協議包括 Dubbo、REST、Thrift、gRPC、JsonRPC、Hessian 等,基本涵蓋了業界大多數主流的 RPC 通信協議。需要注意的是,這些協議的支持都是以直接集成官方 Release 實現的形式來做的,我認為這是一個很好的選擇,既保證了協議解析自身的穩定性,又能使 Dubbo 社區更專注的將更多的精力放在 Dubbo 外圍服務治理能力的改善上。試想如果 Dubbo 社區自己為每個協議提供實現,那是要花費多少精力和時間才能使每種協議達到穩定的生產可用。
除了以上官方提供支持的協議之外,得益于 Dubbo 靈活的擴展機制,想要為 Dubbo 擴展協議非常容易,開發者可以隨時為 Dubbo 增加更多的協議支持,包括自有協議擴展。
關于對 gRPC (HTTP/2) 協議的支持,請參閱《Dubbo 在跨語言和協議穿透性方向的探索:支持 HTTP/2 gRPC》。
多協議能解決的問題
將 RPC 框架無縫地接入 Dubbo 的服務治理體系。
通過協議擴展將 RPC 協議納入 Dubbo 服務開發體系,從而復用 Dubbo 的編程模型和服務發現、流量管控等能力。比如 gRPC,其服務治理體系相對比較弱、編程 API 不夠友好,很難直接用于微服務開發。
滿足不同場景的調用需求。
各個服務可能是為了滿足不同業務需求而開發,同時外圍消費端應用的技術棧也可能多種多樣,通過啟用不同的通信協議,可以最優化不同場景的通信需求。
實現協議間的遷移。
通過支持多種協議,借助注冊中心的協調,可以快速滿足公司內協議遷移的需求。如從自有協議升級到 Dubbo 協議,Dubbo 協議自身升級,從 Dubbo 協議遷移到 gRPC,從 REST 遷移到 Dubbo 協議等。
多注冊中心
當服務集群規模小的時候,一個中心化的集群部署方案能很好的解決我們的業務問題。但是隨著應用規模的增長、用戶流量的增加,我們就不得不考慮要為業務系統引入跨區域、多集群的部署方案,而此時同業務系統密切相關的注冊中心集群也面臨部署方案的選型:
繼續維持全局共享的注冊中心集群。這種架構方案的優點是簡單;缺點是注冊中心集群由于要保存全量的地址數據,存儲和推送壓力會變得很大,另外對于一些注冊中心產品(如 Zookeeper 等)在跨集群網絡部署的場景下穩定性和性能可能都會面臨挑戰。
每個業務集群部署獨立的注冊中心集群。多注冊中心集群的優點是能解決跨集群網絡可用性的問題,同時也能夠減輕注冊中心的存儲和推送壓力;缺點則是要求服務框架(如 Dubbo 等)能有同時發布/監聽多個注冊中心集群的能力。
下面我們具體看一下,Dubbo 為多注冊中心集群場景提供的解決方案。
上圖有兩個業務集群,分別部署在北京和上海,每個業務集群有自己獨立的注冊中心集群,要解決兩個業務集群間服務的透明 RPC 通信問題。
服務提供端,雙注冊中心發布
服務消費端,根據消費需求做單/雙注冊中心訂閱
Dubbo 對異構注冊中心集群的支持
雖然我們會做多注冊中心集群部署,但通常情況下,我們部署的都是相同的注冊中心產品,如都是 Zookeeper、Nacos;而對于注冊中心遷移的場景,則要求 Dubbo 能提供對更多的注冊中心產品的支持,或者最重要的要有很好的擴展能力。Dubbo 官方目前支持的注冊中心實現有:
這里需要特別提到的一點是,當前 Dubbo 的服務注冊/發現模型是以接口為粒度的,而從 2.7.5 版本開始,Dubbo 新引入了應用粒度的服務注冊/發現模型。這一方面有助于優化 Dubbo 當前服務發現機制、提升服務容量,另一方面對于聯通以 SpringCloud 為代表的微服務體系也非常重要(關于這點在下一章中有進一步提及)。更多關于《應用粒度服務發現:服務自省》的介紹,我們將在接下來的文章或文檔中予以補充,請持續關注。
多訂閱帶來的流量調度問題
在引入多注冊中心集群后,Dubbo 在流量選址時的多了一層注冊中心集群間的負載均衡:
在 Cluster Invoker 這一級,我們支持的選址策略有(2.7.5+ 版本,具體使用請參見文檔):
指定優先級
同 zone 優先
權重輪詢
默認,stick to 任意可用
多注冊中心適用的場景
同區域流量優先調度
出于容災或者服務伸縮性需求,服務/應用往往需要部署在多個獨立的機房/區域,在每個區域有獨立注冊中心集群的場景下,實現同區域的流量優先調度就能很好的解決延遲和可用性問題。
注冊中心遷移
公司的服務一直以來可能是存儲在某一個注冊中心,如 Zookeeper,但到了某個時間節點,因為各種各樣的原因,當我們要遷移到另外的注冊中心時,多注冊中心模型能夠保證平滑的遷移。
異構系統互通
不同微服務體系開發的服務,都封閉在各自的服務發現體系中,而通過統一的多注冊中心模型,可以實現不同體系的服務互相發現。
借助 Dubbo 聯通異構的微服務體系
上文我們提到了在組織內存在異構微服務體系的各種合理可能性,現在我們來具體看一下異構微服務體系的實際場景,以及使用 Dubbo 實現互聯互通的解決方法。首先我們先通過一張圖來看一下,聯通異構的微服務體系具體是一個什么樣的場景。
如上圖所示,我們有部分微服務可以是基于 SpringCloud、gRPC、K8S 或者是自建體系構建的,他們各自之間默認是相互隔離無法聯通的。當我們再構建一套基于 Dubbo 的微服務體系時,則利用 Dubbo 的多協議、多服務發現模型,我們就可以做到和各個微服務體系間的兩兩之間的互聯互通。進一步的,如圖中橙色箭頭所示,依賴 Dubbo 體系作為橋接層,我們還可以實現兩個異構微服務體系間的打通。
對于以下幾個示例場景,由于在地址發現層面目前沒有統一的標準,我們暫且假設地址發現層面不同的體系建是沒有障礙的,我們將重點關注遷移的基本流程以及通信協議環節。(關于地址發現部分,我們將在后續《服務自省:基于應用粒度的服務發現》之后再深入探討)
Dubbo 體系內的協議遷移(共存)
絕大多數開發者對 Dubbo 有這么一個固有認知:使用 Dubbo 開發微服務系統,則就要用 Dubbo 協議來作為服務間的通信協議才是最優方案。實際上,我們完全沒有必要只束縛在 Dubbo RPC 協議上。Dubbo 作為微服務開發框架和 Dubbo 作為 RPC 協議這是兩個概念,其實是完全可以分開來看待的,比如我們用 Dubbo 框架開發的業務系統,選用 rest、gRPC 通信是完全沒有問題的(參加 Dubbo 支持的協議列表),具體用什么協議根據業務特點和技術規劃才是最適合的。
當前在云原生、Mesh 的大背景下, HTTP1/2、gRPC 協議開始受到越來越多的關注,一方面原因自然是因為它們在標準化方面做的更好,得到的更多的網絡設備和基礎設施的支持,具備更好的通用性和穿透性。對于很多有云原生遷移意愿的企業來說,往此類協議遷移無疑將對之后的架構升級有更多的幫助。
下圖演示了在 Dubbo 體系內,從 Dubbo 協議向 gRPC 協議遷移的一個中間狀態。
最左邊的代表尚未遷移的老應用,這類應用在遷移過程中仍然要消費和提供 Dubbo 協議的服務。
中間的代表處于遷移中的應用,他們中間可能有些是服務提供者,既要為左邊的老系統提供提供 Dubbo 協議服務;又要為右邊的新系統提供 gRPC 服務;因此他們都是雙協議暴露服務。
最右邊則代表是新開發的或者已經遷移完成的應用,這個體系內已能完全用 gRPC 協議通信。
最終度過中間態后,我們期望所有的應用都達到最左邊應用的狀態,實現完全的 gRPC 協議通信。
Spring Cloud 體系遷移到 Dubbo 體系(共存)
如前文所述,由于 SpringCloud 和 Dubbo 間服務發現模型的問題,要兩個體系間的地址互通需要 Dubbo 側作相應的適配,關于這部分內容將在接下來的 2.7.5 版本《服務自省》部分發布,在此我們暫且認為已經打通。
Dubbo 體系內的部分應用作為透明的聯通兩個體系的關鍵節點,部分服務提供者應用要雙協議發布、部分消費者應用要做到選定協議消費。由于老的 Spring Cloud 體系不允許做任何改動,因此聯通兩套體系的關鍵是 REST 協議,對 Dubbo 側的應用來說:
部分應用可能要以 REST 協議消費 SpringCloud 的服務;
部分應用可能要暴露 REST 協議共 SpringCloud 消費;
Dubbo 自有體系內則通過自己選定的協議通信,這里就比較靈活了,可以是 Dubbo、REST、gRPC 等其中的任一種。而如果選定 REST 協議則對于與 SpringCloud 體系的聯通就變得更加自然了,因為兩端的協議都是統一的。
對于消費 Spring Cloud 服務的應用,要配置服務 :
對于提供服務給 Spring Cloud 側消費的應用,則指定服務暴露為 rest 協議,或者雙協議暴露(因如果這個服務還要被新體系內的應用調用到):
作為 Dubbo 的維護者,雖然我們這里有明顯的偏向性,講的是從如何從 SpringCloud 體系遷移到 Dubbo 體系。但是反過來考慮,如果你已經或者即將選型 Dubbo 來開發微服務,則未來從 Dubbo 遷移到 SpringCloud 也是同樣的思路,Dubbo 的多協議、多注冊模型為雙向遷移都提供了同樣的靈活性。
評論
查看更多