從編程開發的角度來講,Apache Dubbo (如下簡稱 Dubbo )首先是一款 RPC 服務框架,它最大的優點在於提供了面向接口代理的服務編程模型,對開發者屏蔽了底層的遠程通訊細節。同時 Dubbo 也是一款服務治理框架,它爲分佈式部署的微服務提供了服務發現、流量調度等服務治理解決方案。apache
在這篇文章中,咱們將以以上基礎能力爲背景,嘗試突破 Dubbo 體系自身,探索如何利用 Dubbo 對多協議、多服務發現模型的支持,來實現異構微服務體系間的互聯互通。在實際業務場景中,這能夠用來解決異構技術體系共存場景下的通訊問題,幫助公司實如今異構技術體系間做平滑遷移,解決大規模跨區域、多集羣部署場景的地址發現及流量調度等問題。編程
咱們仍是從 Dubbo 是一個微服務開發框架 這個你們熟知的概念開始。就像 Spring 是開發 Java 應用的基礎框架同樣,咱們常常會選用 Dubbo 做爲開發微服務業的基礎框架。 Dubbo 框架的最大優點我認爲就在其面向接口的編程模型,使得開發遠程服務調用就像開發本地服務同樣(以 Java 語言爲例):api
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 目前是支持多協議、多註冊中心的,能夠說就是爲解決咱們上面分析的 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
。
如下是具體的代碼配置:
<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"/>
<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"/>
<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》。
經過協議擴展將 RPC 協議歸入 Dubbo 服務開發體系,從而複用 Dubbo 的編程模型和服務發現、流量管控等能力。好比 gRPC,其服務治理體系相對比較弱、編程 API 不夠友好,很難直接用於微服務開發。
各個服務多是爲了知足不一樣業務需求而開發,同時外圍消費端應用的技術棧也可能多種多樣,經過啓用不一樣的通訊協議,能夠最優化不一樣場景的通訊需求。
經過支持多種協議,藉助註冊中心的協調,能夠快速知足公司內協議遷移的需求。如從自有協議升級到 Dubbo 協議,Dubbo 協議自身升級,從 Dubbo 協議遷移到 gRPC,從 REST 遷移到 Dubbo 協議等。
當服務集羣規模小的時候,一箇中心化的集羣部署方案能很好的解決咱們的業務問題。可是隨着應用規模的增加、用戶流量的增長,咱們就不得不考慮要爲業務系統引入跨區域、多集羣的部署方案,而此時同業務系統密切相關的註冊中心集羣也面臨部署方案的選型:
下面咱們具體看一下,Dubbo 爲多註冊中心集羣場景提供的解決方案。
上圖有兩個業務集羣,分別部署在北京和上海,每一個業務集羣有本身獨立的註冊中心集羣,要解決兩個業務集羣間服務的透明 RPC 通訊問題。
<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"/>
<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+ 版本,具體使用請參見文檔):
指定優先級
<!-- 來自 preferred=「true」 註冊中心的地址將被優先選擇,只有該中心無可用地址時才 Fallback 到其餘註冊中心 --> <dubbo:registry address="zookeeper://${zookeeper.address1}" preferred="true" />
同 zone 優先
<!-- 選址時會和流量中的 zone key 作匹配,流量會優先派發到相同 zone 的地址 --> <dubbo:registry address="zookeeper://${zookeeper.address1}" zone="beijing" />
權重輪詢
<!-- 來自北京和上海集羣的地址,將以 10:1 的比例來分配流量 --> <dubbo:registry id="beijing" address="zookeeper://${zookeeper.address1}" weight=」100「 /> <dubbo:registry id="shanghai" address="zookeeper://${zookeeper.address2}" weight=」10「 />
出於容災或者服務伸縮性需求,服務/應用每每須要部署在多個獨立的機房/區域,在每一個區域有獨立註冊中心集羣的場景下,實現同區域的流量優先調度就能很好的解決延遲和可用性問題。
公司的服務一直以來多是存儲在某一個註冊中心,如 Zookeeper,但到了某個時間節點,由於各類各樣的緣由,當咱們要遷移到另外的註冊中心時,多註冊中心模型可以保證平滑的遷移。
不一樣微服務體系開發的服務,都封閉在各自的服務發現體系中,而經過統一的多註冊中心模型,能夠實現不一樣體系的服務互相發現。
上文咱們提到了在組織內存在異構微服務體系的各類合理可能性,如今咱們來具體看一下異構微服務體系的實際場景,以及使用 Dubbo 實現互聯互通的解決方法。首先咱們先經過一張圖來看一下,聯通異構的微服務體系具體是一個什麼樣的場景。
如上圖所示,咱們有部分微服務能夠是基於 SpringCloud、gRPC、K8S 或者是自建體系構建的,他們各自之間默認是相互隔離沒法聯通的。當咱們再構建一套基於 Dubbo 的微服務體系時,則利用 Dubbo 的多協議、多服務發現模型,咱們就能夠作到和各個微服務體系間的兩兩之間的互聯互通。進一步的,如圖中橙色箭頭所示,依賴 Dubbo 體系做爲橋接層,咱們還能夠實現兩個異構微服務體系間的打通。
對於如下幾個示例場景,因爲在地址發現層面目前沒有統一的標準,咱們暫且假設地址發現層面不一樣的體系建是沒有障礙的,咱們將重點關注遷移的基本流程以及通訊協議環節。(關於地址發現部分,咱們將在後續《服務自省:基於應用粒度的服務發現》以後再深刻探討)
絕大多數開發者對 Dubbo 有這麼一個固有認知:使用 Dubbo 開發微服務系統,則就要用 Dubbo 協議來做爲服務間的通訊協議纔是最優方案。實際上,咱們徹底沒有必要只束縛在 Dubbo RPC 協議上。Dubbo 做爲微服務開發框架和 Dubbo 做爲 RPC 協議這是兩個概念,實際上是徹底能夠分開來看待的,好比咱們用 Dubbo 框架開發的業務系統,選用 rest、gRPC 通訊是徹底沒有問題的(參加 Dubbo 支持的協議列表),具體用什麼協議根據業務特色和技術規劃纔是最適合的。
當前在雲原生、Mesh 的大背景下, HTTP1/二、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 的多協議、多註冊模型爲雙向遷移都提供了一樣的靈活性。
本文爲阿里雲內容,未經容許不得轉載。