一、介紹
Apollo(阿波羅)[參考附錄](méi)是攜程框架部研發(fā)并開(kāi)源的一款生產(chǎn)級(jí)的配置中心產(chǎn)品,它能夠集中管理應(yīng)用在不同環(huán)境、不同集群的配置,配置修改后能夠?qū)崟r(shí)推送到應(yīng)用端,并且具備規(guī)范的權(quán)限、流程治理等特性,適用于微服務(wù)配置管理場(chǎng)景。
Apollo目前在國(guó)內(nèi)開(kāi)發(fā)者社區(qū)比較熱,在Github上有超過(guò)5k顆星,在國(guó)內(nèi)眾多互聯(lián)網(wǎng)公司有落地案例,可以說(shuō)Apollo是目前配置中心產(chǎn)品領(lǐng)域Number1的產(chǎn)品,其成熟度和企業(yè)級(jí)特性要遠(yuǎn)遠(yuǎn)強(qiáng)于Spring Cloud體系中的Spring Cloud Config產(chǎn)品。
Apollo采用分布式微服務(wù)架構(gòu),它的架構(gòu)有一點(diǎn)復(fù)雜,Apollo的作者宋順雖然給出了一個(gè)架構(gòu)圖,但是如果沒(méi)有一定的分布式微服務(wù)架構(gòu)基礎(chǔ)的話,則普通的開(kāi)發(fā)人員甚至是架構(gòu)師也很難一下子理解。為了讓大家更好的理解Apollo的架構(gòu)設(shè)計(jì),我花了一點(diǎn)時(shí)間把Apollo的架構(gòu)按我的方式重新剖析一把。只有完全理解了Apollo的架構(gòu),大家才能在生產(chǎn)實(shí)踐中更好的部署和使用Apollo。另外,通過(guò)學(xué)習(xí)Apollo的架構(gòu),大家可以深入理解微服務(wù)架構(gòu)的一些基本原理。
二、架構(gòu)和模塊
下圖是Apollo的作者給出的架構(gòu)圖:

如果沒(méi)有足夠的分布式微服務(wù)架構(gòu)的基礎(chǔ),對(duì)攜程的一些框架產(chǎn)品(比如Software Load Balancer(SLB))不了解的話,那么這個(gè)架構(gòu)圖第一眼看是不太好理解的(其實(shí)我第一次看到這個(gè)架構(gòu)也沒(méi)有看明白)。在這里我們先放一下,等我后面把這個(gè)架構(gòu)再重新剖析一把以后,大家再回過(guò)頭來(lái)看這個(gè)架構(gòu)就容易理解了。
下面是Apollo的七個(gè)模塊,其中四個(gè)模塊是和功能相關(guān)的核心模塊,另外三個(gè)模塊是輔助服務(wù)發(fā)現(xiàn)的模塊:
四個(gè)核心模塊及其主要功能
1. ConfigService
提供配置獲取接口
提供配置推送接口
服務(wù)于Apollo客戶端
2. AdminService
提供配置管理接口
提供配置修改發(fā)布接口
服務(wù)于管理界面Portal
3. Client
為應(yīng)用獲取配置,支持實(shí)時(shí)更新
通過(guò)MetaServer獲取ConfigService的服務(wù)列表
使用客戶端軟負(fù)載SLB方式調(diào)用ConfigService
4. Portal
配置管理界面
通過(guò)MetaServer獲取AdminService的服務(wù)列表
使用客戶端軟負(fù)載SLB方式調(diào)用AdminService
三個(gè)輔助服務(wù)發(fā)現(xiàn)模塊
1. Eureka
用于服務(wù)發(fā)現(xiàn)和注冊(cè)
Config/AdminService注冊(cè)實(shí)例并定期報(bào)心跳
和ConfigService住在一起部署
2. MetaServer
Portal通過(guò)域名訪問(wèn)MetaServer獲取AdminService的地址列表
Client通過(guò)域名訪問(wèn)MetaServer獲取ConfigService的地址列表
相當(dāng)于一個(gè)Eureka Proxy
邏輯角色,和ConfigService住在一起部署
3. NginxLB
和域名系統(tǒng)配合,協(xié)助Portal訪問(wèn)MetaServer獲取AdminService地址列表
和域名系統(tǒng)配合,協(xié)助Client訪問(wèn)MetaServer獲取ConfigService地址列表
和域名系統(tǒng)配合,協(xié)助用戶訪問(wèn)Portal進(jìn)行配置管理
三、架構(gòu)剖析
Apollo架構(gòu)V1
如果不考慮分布式微服務(wù)架構(gòu)中的服務(wù)發(fā)現(xiàn)問(wèn)題,Apollo的最簡(jiǎn)架構(gòu)如下圖所示:

要點(diǎn):
ConfigService是一個(gè)獨(dú)立的微服務(wù),服務(wù)于Client進(jìn)行配置獲取。
Client和ConfigService保持長(zhǎng)連接,通過(guò)一種拖拉結(jié)合(push & pull)的模式,實(shí)現(xiàn)配置實(shí)時(shí)更新的同時(shí),保證配置更新不丟失。
AdminService是一個(gè)獨(dú)立的微服務(wù),服務(wù)于Portal進(jìn)行配置管理。Portal通過(guò)調(diào)用AdminService進(jìn)行配置管理和發(fā)布。
ConfigService和AdminService共享ConfigDB,ConfigDB中存放項(xiàng)目在某個(gè)環(huán)境的配置信息。ConfigService/AdminService/ConfigDB三者在每個(gè)環(huán)境(DEV/FAT/UAT/PRO)中都要部署一份。
Protal有一個(gè)獨(dú)立的PortalDB,存放用戶權(quán)限、項(xiàng)目和配置的元數(shù)據(jù)信息。Protal只需部署一份,它可以管理多套環(huán)境。
Apollo架構(gòu)V2
為了保證高可用,ConfigService和AdminService都是無(wú)狀態(tài)以集群方式部署的,這個(gè)時(shí)候就存在一個(gè)服務(wù)發(fā)現(xiàn)問(wèn)題:Client怎么找到ConfigService?Portal怎么找到AdminService?為了解決這個(gè)問(wèn)題,Apollo在其架構(gòu)中引入了Eureka服務(wù)注冊(cè)中心組件,實(shí)現(xiàn)微服務(wù)間的服務(wù)注冊(cè)和發(fā)現(xiàn),更新后的架構(gòu)如下圖所示:

要點(diǎn):
Config/AdminService啟動(dòng)后都會(huì)注冊(cè)到Eureka服務(wù)注冊(cè)中心,并定期發(fā)送?;钚奶?。
Eureka采用集群方式部署,使用分布式一致性協(xié)議保證每個(gè)實(shí)例的狀態(tài)最終一致。
Apollo架構(gòu)V3
我們知道Eureka是自帶服務(wù)發(fā)現(xiàn)的Java客戶端的,如果Apollo只支持Java客戶端接入,不支持其它語(yǔ)言客戶端接入的話,那么Client和Portal只需要引入Eureka的Java客戶端,就可以實(shí)現(xiàn)服務(wù)發(fā)現(xiàn)功能。發(fā)現(xiàn)目標(biāo)服務(wù)后,通過(guò)客戶端軟負(fù)載(SLB,例如Ribbon)就可以路由到目標(biāo)服務(wù)實(shí)例。這是一個(gè)經(jīng)典的微服務(wù)架構(gòu),基于Eureka實(shí)現(xiàn)服務(wù)注冊(cè)發(fā)現(xiàn)+客戶端Ribbon配合實(shí)現(xiàn)軟路由,如下圖所示:

Apollo架構(gòu)V4
在攜程,應(yīng)用場(chǎng)景不僅有Java,還有很多遺留的.Net應(yīng)用。Apollo的作者也考慮到開(kāi)源到社區(qū)以后,很多客戶應(yīng)用是非Java的。但是Eureka(包括Ribbon軟負(fù)載)原生僅支持Java客戶端,如果要為多語(yǔ)言開(kāi)發(fā)Eureka/Ribbon客戶端,這個(gè)工作量很大也不可控。為此,Apollo的作者引入了MetaServer這個(gè)角色,它其實(shí)是一個(gè)Eureka的Proxy,將Eureka的服務(wù)發(fā)現(xiàn)接口以更簡(jiǎn)單明確的HTTP接口的形式暴露出來(lái),方便Client/Protal通過(guò)簡(jiǎn)單的HTTPClient就可以查詢到Config/AdminService的地址列表。獲取到服務(wù)實(shí)例地址列表之后,再以簡(jiǎn)單的客戶端軟負(fù)載(Client SLB)策略路由定位到目標(biāo)實(shí)例,并發(fā)起調(diào)用。
現(xiàn)在還有一個(gè)問(wèn)題,MetaServer本身也是無(wú)狀態(tài)以集群方式部署的,那么Client/Protal該如何發(fā)現(xiàn)MetaServer呢?一種傳統(tǒng)的做法是借助硬件或者軟件負(fù)載均衡器,例如在攜程采用的是擴(kuò)展后的NginxLB(也稱Software Load Balancer),由運(yùn)維為MetaServer集群配置一個(gè)域名,指向NginxLB集群,NginxLB再對(duì)MetaServer進(jìn)行負(fù)載均衡和流量轉(zhuǎn)發(fā)。Client/Portal通過(guò)域名+NginxLB間接訪問(wèn)MetaServer集群。
引入MetaServer和NginxLB之后的架構(gòu)如下圖所示:

Apollo架構(gòu)V5
V4版本已經(jīng)是比較完成的Apollo架構(gòu)全貌,現(xiàn)在還剩下最后一個(gè)環(huán)節(jié):Portal也是無(wú)狀態(tài)以集群方式部署的,用戶如何發(fā)現(xiàn)和訪問(wèn)Portal?答案也是簡(jiǎn)單的傳統(tǒng)做法,用戶通過(guò)域名+NginxLB間接訪問(wèn)Portal集群。
所以V5版本是包括用戶端的最終的Apollo架構(gòu)全貌,如下圖所示:

四、結(jié)論
1. 經(jīng)過(guò)我在第三部分的剖析之后,相信大家對(duì)Apollo的微服務(wù)架構(gòu)會(huì)有更清晰的認(rèn)識(shí),作為一個(gè)思考題,大家再回頭看一下第二部分宋順給出的架構(gòu)圖,現(xiàn)在是否能夠理解?它和我的架構(gòu)是如何對(duì)應(yīng)的?提示一下,宋順的視角是一個(gè)從上往下的俯視視角,而我的是一個(gè)側(cè)面視角。
2. ConfgService/AdminService/Client/Portal是Apollo的四個(gè)核心微服務(wù)模塊,相互協(xié)作完成配置中心業(yè)務(wù)功能,Eureka/MetaServer/NginxLB是輔助微服務(wù)之間進(jìn)行服務(wù)發(fā)現(xiàn)的模塊。
3. Apollo采用微服務(wù)架構(gòu)設(shè)計(jì),架構(gòu)和部署都有一些復(fù)雜,但是每個(gè)服務(wù)職責(zé)單一,易于擴(kuò)展。另外,Apollo只需要一套Portal就可以集中管理多套環(huán)境(DEV/FAT/UAT/PRO)中的配置,這個(gè)是它的架構(gòu)的一大亮點(diǎn)。。
4. 服務(wù)發(fā)現(xiàn)是微服務(wù)架構(gòu)的基礎(chǔ),在Apollo的微服務(wù)架構(gòu)中,既采用Eureka注冊(cè)中心式的服務(wù)發(fā)現(xiàn),也采用NginxLB集中Proxy式的服務(wù)發(fā)現(xiàn)。