您好,登錄后才能下訂單哦!
從編程開發的角度來說,Apache Dubbo (以下簡稱 Dubbo)首先是一款 RPC 服務框架,它最大的優勢在于提供了面向接口代理的服務編程模型,對開發者屏蔽了底層的遠程通信細節。同時 Dubbo 也是一款服務治理框架,它為分布式部署的微服務提供了服務發現、流量調度等服務治理解決方案。
在這篇文章中,我們將以以上基礎能力為背景,嘗試突破 Dubbo 體系自身,探索如何利用 Dubbo 對多協議、多服務發現模型的支持,來實現異構微服務體系間的互聯互通。在實際業務場景中,這可以用來解決異構技術體系共存場景下的通信問題,幫助公司實現在異構技術體系間作平滑遷移,解決大規模跨區域、多集群部署場景的地址發現及流量調度等問題。
我們還是從 Dubbo 是一個微服務開發框架 這個大家熟知的概念開始。就像 Spring 是開發 Java 應用的基礎框架一樣,我們經常會選用 Dubbo 作為開發微服務業的基礎框架。Dubbo 框架的最大優勢我認為就在其面向接口的編程模型,使得開發遠程服務調用就像開發本地服務一樣(以 Java 語言為例):
1、服務定義
public interface GreetingsService {
String sayHi(String name);
}
2、消費方調用服務
// 和調用本地服務一樣,完全透明。
@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 目前是支持多協議、多注冊中心的,可以說就是為解決我們上面分析的 Dubbo 同構體系內的場景而設計的,因此下面我們從同構體系的多協議、多注冊中心場景講起,先了解 Dubbo 多協議、多注冊中心的基本支持情況以及它們是如何工作的。而在后面的一章再進一步探索怎么擴展這個能力來支持異構微服務體系的互聯互通。
我們將通過兩個場景示例,來分別具體的講一下 Dubbo 的多協議、多注冊中心機制的使用方式和工作原理。
以上是使用 Dubbo 開發的一套微服務,服務間通信使用到了不同的協議,根據我們的調研發現,公司內部啟用多協議其實是非常普遍需求,具體場景在此我們暫不做解釋。
應用 B 作為服務提供者,發布了 5 個服務,其中:
應用 A 作為消費者,使用 dubbo 協議消費 DemoService1 DemoService2,使用 gRPC 協議消費 DemoService0。
應用 B 作為消費者,使用 gRPC 協議消費 DemoService2 DemoService4,使用 dubbo 協議消費 DemoService0。
以下是具體的代碼配置:
1、提供端應用 B
<dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService1" protocol="dubbo"/>
<dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService2" protocol="dubbo"/>
<dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService3" protocol="grpc"/>
<dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService4" protocol="grpc"/>
<dubbo:service interface="org.apache.dubbo.samples.basic.api.DemoService0" protocol="dubbo, grpc"/>
2、消費端應用 A
<dubbo:reference protocol="dubbo" interface="org.apache.dubbo.samples.basic.api.DemoService1"/>
<dubbo:reference protocol="dubbo" interface="org.apache.dubbo.samples.basic.api.DemoService2"/>
<dubbo:reference protocol="grpc" interface="org.apache.dubbo.samples.basic.api.DemoService0"/>
3、消費端應用C
<dubbo:reference protocol="grpc" interface="org.apache.dubbo.samples.basic.api.DemoService3"/>
<dubbo:reference protocol="grpc" interface="org.apache.dubbo.samples.basic.api.DemoService4"/>
<dubbo:reference protocol="dubbo" interface="org.apache.dubbo.samples.basic.api.DemoService0"/>
Dubbo 目前所支持的協議包括 Dubbo、REST、Thrift、gRPC、JsonRPC、Hessian 等,基本涵蓋了業界大多數主流的 RPC 通信協議。需要注意的是,這些協議的支持都是以直接集成官方 Release 實現的形式來做的,我認為這是一個很好的選擇,既保證了協議解析自身的穩定性,又能使 Dubbo 社區更專注的將更多的精力放在 Dubbo 外圍服務治理能力的改善上。試想如果 Dubbo 社區自己為每個協議提供實現,那是要花費多少精力和時間才能使每種協議達到穩定的生產可用。
除了以上官方提供支持的協議之外,得益于 Dubbo 靈活的擴展機制,想要為 Dubbo 擴展協議非常容易,開發者可以隨時為 Dubbo 增加更多的協議支持,包括自有協議擴展。
關于對 gRPC (HTTP/2) 協議的支持,請參閱《Dubbo 在跨語言和協議穿透性方向的探索:支持 HTTP/2 gRPC》。
多協議能解決的問題
當服務集群規模小的時候,一個中心化的集群部署方案能很好的解決我們的業務問題。但是隨著應用規模的增長、用戶流量的增加,我們就不得不考慮要為業務系統引入跨區域、多集群的部署方案,而此時同業務系統密切相關的注冊中心集群也面臨部署方案的選型:
1、繼續維持全局共享的注冊中心集群。這種架構方案的優點是簡單;缺點是注冊中心集群由于要保存全量的地址數據,存儲和推送壓力會變得很大,另外對于一些注冊中心產品(如 Zookeeper 等)在跨集群網絡部署的場景下穩定性和性能可能都會面臨挑戰。
2、每個業務集群部署獨立的注冊中心集群。多注冊中心集群的優點是能解決跨集群網絡可用性的問題,同時也能夠減輕注冊中心的存儲和推送壓力;缺點則是要求服務框架(如 Dubbo 等)能有同時發布/監聽多個注冊中心集群的能力。
下面我們具體看一下,Dubbo 為多注冊中心集群場景提供的解決方案。
上圖有兩個業務集群,分別部署在北京和上海,每個業務集群有自己獨立的注冊中心集群,要解決兩個業務集群間服務的透明 RPC 通信問題。
1、服務提供端,雙注冊中心發布
<dubbo:registry id="beijingRegistry" address="zookeeper://${zookeeper.address1}" default="false"/>
<dubbo:registry id="shanghaiRegistry" address="zookeeper://${zookeeper.address2}" />
<dubbo:service interface="org.apache.dubbo.samples.multi.registry.api.HelloService" ref="helloService" registry="shanghaiRegistry,beijingRegistry"/>
<dubbo:service interface="org.apache.dubbo.samples.multi.registry.api.DemoService" ref="demoService" registry="shanghaiRegistry,beijingRegistry"/>
2、服務消費端,根據消費需求做單/雙注冊中心訂閱
<dubbo:registry id="beijingRegistry" address="zookeeper://${zookeeper.address1}" default="false" preferred="true" weight="100"/>
<dubbo:registry id="shanghaiRegistry" address="zookeeper://${zookeeper.address2}" default="true" weight="20"/>
<dubbo:reference interface="org.apache.dubbo.samples.multi.registry.api.DemoService"/>
<dubbo:reference interface="org.apache.dubbo.samples.multi.registry.api.DemoService" registry="beijingRegistry, shanghaiRegistry"/>
<dubbo:reference interface="org.apache.dubbo.samples.multi.registry.api.HelloService" registry="beijingRegistry"/>
<dubbo:reference interface="org.apache.dubbo.samples.multi.registry.api.HelloService" registry="shanghaiRegistry,shanghaiRegistry"/>
雖然我們會做多注冊中心集群部署,但通常情況下,我們部署的都是相同的注冊中心產品,如都是 Zookeeper、Nacos;而對于注冊中心遷移的場景,則要求 Dubbo 能提供對更多的注冊中心產品的支持,或者最重要的是要有很好的擴展能力。Dubbo 官方目前支持的注冊中心實現有:
這里需要特別提到的一點是,當前 Dubbo 的服務注冊/發現模型是以接口為粒度的,而從 2.7.5 版本開始,Dubbo 新引入了應用粒度的服務注冊/發現模型。這一方面有助于優化 Dubbo 當前服務發現機制、提升服務容量,另一方面對于聯通以 SpringCloud 為代表的微服務體系也非常重要(關于這點在下一章中有進一步提及)。更多關于《應用粒度服務發現:服務自省》的介紹,我們將在接下來的文章或文檔中予以補充,請持續關注。
在引入多注冊中心集群后,Dubbo 在流量選址時的多了一層注冊中心集群間的負載均衡:
在 Cluster Invoker 這一級,我們支持的選址策略有(2.7.5+ 版本,具體使用請參見文檔):
1、指定優先級
<!-- 來自 preferred=“true” 注冊中心的地址將被優先選擇,只有該中心無可用地址時才 Fallback 到其他注冊中心 -->
<dubbo:registry address="zookeeper://${zookeeper.address1}" preferred="true" />
2、同 zone 優先
<!-- 選址時會和流量中的 zone key 做匹配,流量會優先派發到相同 zone 的地址 -->
<dubbo:registry address="zookeeper://${zookeeper.address1}" zone="beijing" />
3、權重輪選
<!-- 來自北京和上海集群的地址,將以 10:1 的比例來分配流量 -->
<dubbo:registry id="beijing" address="zookeeper://${zookeeper.address1}" weight=”100“ />
<dubbo:registry id="shanghai" address="zookeeper://${zookeeper.address2}" weight=”10“ />
4、默認,stick to 任意可用
上文我們提到了在組織內存在異構微服務體系的各種合理可能性,現在我們來具體看一下異構微服務體系的實際場景,以及使用 Dubbo 實現互聯互通的解決方法。首先我們先通過一張圖來看一下,聯通異構的微服務體系具體是一個什么樣的場景。
如上圖所示,我們有部分微服務可以是基于 SpringCloud、gRPC、K8S 或者是自建體系構建的,他們各自之間默認是相互隔離無法聯通的。當我們再構建一套基于 Dubbo 的微服務體系時,則利用 Dubbo 的多協議、多服務發現模型,我們就可以做到和各個微服務體系間的兩兩之間的互聯互通。進一步的,如圖中橙色箭頭所示,依賴 Dubbo 體系作為橋接層,我們還可以實現兩個異構微服務體系間的打通。
對于以下幾個示例場景,由于在地址發現層面目前沒有統一的標準,我們暫且假設地址發現層面不同的體系建是沒有障礙的,我們將重點關注遷移的基本流程以及通信協議環節。(關于地址發現部分,我們將在后續《服務自省:基于應用粒度的服務發現》之后再深入探討)
絕大多數開發者對 Dubbo 有這么一個固有認知:使用 Dubbo 開發微服務系統,則就要用 Dubbo 協議來作為服務間的通信協議才是最優方案。實際上,我們完全沒有必要只束縛在 Dubbo RPC 協議上。Dubbo 作為微服務開發框架和 Dubbo 作為 RPC 協議這是兩個概念,其實是完全可以分開來看待的,比如我們用 Dubbo 框架開發的業務系統,選用 rest、gRPC 通信是完全沒有問題的(參加 Dubbo 支持的協議列表),具體用什么協議根據業務特點和技術規劃才是最適合的。
當前在云原生、Mesh 的大背景下, HTTP1/2、gRPC 協議開始受到越來越多的關注,一方面原因自然是因為它們在標準化方面做的更好,得到的更多的網絡設備和基礎設施的支持,具備更好的通用性和穿透性。對于很多有云原生遷移意愿的企業來說,往此類協議遷移無疑將對之后的架構升級有更多的幫助。
下圖演示了在 Dubbo 體系內,從 Dubbo 協議向 gRPC 協議遷移的一個中間狀態。
如前文所述,由于 SpringCloud 和 Dubbo 間服務發現模型的問題,要兩個體系間的地址互通需要 Dubbo 側作相應的適配,關于這部分內容將在接下來的 2.7.5 版本《服務自省》部分發布,在此我們暫且認為已經打通。
Dubbo 體系內的部分應用作為透明的聯通兩個體系的關鍵節點,部分服務提供者應用要雙協議發布、部分消費者應用要做到選定協議消費。由于老的 Spring Cloud 體系不允許做任何改動,因此聯通兩套體系的關鍵是 REST 協議,對 Dubbo 側的應用來說:
對于消費 Spring Cloud 服務的應用,要配置服務 :
<dubbo:reference interface ="xxx.SpringService" protocol="rest"/>
對于提供服務給 Spring Cloud 側消費的應用,則指定服務暴露為 rest 協議,或者雙協議暴露(因如果這個服務還要被新體系內的應用調用到):
<dubbo:service interface="xxx.NewService" protocol="rest,dubbo"/>
作為 Dubbo 的維護者,雖然我們這里有明顯的偏向性,講的是從如何從 SpringCloud 體系遷移到 Dubbo 體系。但是反過來考慮,如果你已經或者即將選型 Dubbo 來開發微服務,則未來從 Dubbo 遷移到 SpringCloud 也是同樣的思路,Dubbo 的多協議、多注冊模型為雙向遷移都提供了同樣的靈活性。
這個場景和上一節中講到的的 SpringCloud 遷移有些類似,最大的區別在于 rest 協議是 Dubbo 官方默認提供支持的,而對于已有的微服務體系內的私有通信協議,則需要先要自己去擴展 Dubbo Protocol 來提供協議層面的支持,關于 Protocol 如何擴展請參見以下官方文檔:
http://dubbo.apache.org/zh-cn/docs/dev/impls/protocol.html
要實現異構微服務體系間的共存或遷移,關鍵點在打通異構體系間的協議與服務發現,得益于 Dubbo 自身對多協議、多注冊模型的支持,我們可以很容易的使 Dubbo 成為橋接異構微服務體系的中間層。熟悉 Dubbo 多協議實現細節的同學,可能會擔心在服務數量較多的場景下,多協議注冊會導致地址數量翻倍從而影響地址推送性能。
另外,在本文“借助 Dubbo 聯通異構的微服務體系”一節中,關于如何實現異構體系間的透明服務發現部分,我們沒有做詳細的說明。涉及服務發現的這部分,我們將在接下來的文章中做具體闡述,看看 Dubbo 2.7.5 版本引入新的服務發現機制是如何解決這個問題的,請持續關注后續文章及 Dubbo 官方文檔。
作者信息:
劉軍,GitHub 賬號 Chickenlj,Apache Dubbo PMC,項目核心維護者,見證了 Dubbo 從重啟開源到 Apache 畢業的整個流程。現任職阿里云云原生應用平臺團隊,參與服務框架、微服務相關工作,目前主要在推動 Dubbo 開源的云原生化。
“阿里巴巴云原生關注微服務、Serverless、容器、Service Mesh 等技術領域、聚焦云原生流行技術趨勢、云原生大規模的落地實踐,做最懂云原生開發者的技術圈。”
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。