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