Apollo架構設計
上一篇部落格有講到:【Apollo】(1)--- Apollo入門介紹篇
這篇來寫Apollo的核心架構設計
一、整體架構
Apollo整體架構圖,已由作者宋順已經給出:
這幅圖所描述的已經很清楚了。下面來具體解釋下上面這張圖。
1、四個主要模組和核心功能
ConfigService
提供配置的讀取、推送等功能,服務物件是Apollo客戶端(client)(最終目的就是把配置資料給到我們自己的微服務物件)
Admin Service
提供配置的修改、釋出等功能,服務物件是Apollo Portal(管理介面)(簡單理解成就是就是用來在配置中心管理介面來新增或者修改配置)
Client( 客戶端)
Apollo提供的客戶端程式,為應用提供配置獲取、實時更新等功能。
域名訪問 Meta Server 獲取 Config Service 服務列表(IP+Port),而後直接通過IP+Port訪問服務,同時在Client側會做負載均衡、錯誤重試
Portal
提供Web介面供使用者管理配置。
Portal通過域名訪問 Meta Server 獲取 Admin Service 服務列表(IP+Port),而後直接通過IP+Port訪問服務,同時在Portal側會做 負載均衡、錯誤重試
個人理解這四個模組
ConfigService 和 Client 的配合
從這裡面可以看出我們自己的微服務不是直接和ConfigService打交道的,而是跟Client打交道,Client才是真正和ConfigService打交道來獲取最新配置資訊。
Admin Service 和 Portal
這裡分類兩個模組就很好理解了,因為管理介面的實現有自己的一套程式碼,而且管理介面操作的一些許可權等資訊,只會跟它自己有關係,對於微服務來講,我只關心有沒有配置
這條配置資料,而不會去關心在管理介面上什麼使用者能夠新增配置資訊。所以就有Portal對於了兩個資料庫,一個可以理解是它自己的,存放一些許可權等資訊,另一部分是和
配置有關的,所以通過 Admin Service 存放在 configDB 中。
2、三個輔助服務發現模組
為了保證上面四個模組的高可用,所以這裡需要三個輔助模組配合。
Eureka
用於服務發現和註冊Config/AdminService註冊例項並定期報心跳。
為了簡化部署,我們實際上會把Config Service、Eureka和Meta Server三個邏輯角色部署在同一個JVM程式中
官方也有解釋為什麼我們採用Eureka作為服務註冊中心,而不是使用傳統的zk、etcd呢?我大致總結了一下,有以下幾方面的原因:
1)它提供了完整的Service Registry和Service Discovery實現
首先是提供了完整的實現,並且也經受住了Netflix自己的生產環境考驗,相對使用起來會比較省心。
2)和Spring Cloud無縫整合
我們的專案本身就使用了Spring Cloud和Spring Boot,同時Spring Cloud還有一套非常完善的開原始碼來整合Eureka,所以使用起來非常方便。另外,Eureka還支援在
我們應用自身的容器中啟動,也就是說我們的應用啟動完之後,既充當了Eureka的角色,同時也是服務的提供者。這樣就極大的提高了服務的可用性。這一點是我們選擇
Eureka而不是zk、etcd等的主要原因,為了提高配置中心的可用性和降低部署複雜度,我們需要儘可能地減少外部依賴。
3)Open Source
最後一點是開源,由於程式碼是開源的,所以非常便於我們瞭解它的實現原理和排查問題。
MetaServer
Portal通過域名 訪問 MetaServer 獲取 AdminService 的地址列表。
Client通過域名訪問MetaServer獲取ConfigService的地址列表。
相當於一個Eureka Proxy 邏輯角色,和ConfigService住在一起部署。
NginxLB
和域名系統配合,協助Portal訪問MetaServer獲取AdminService地址列表。
和域名系統配合,協助Client訪問MetaServer獲取ConfigService地址列表。
和域名系統配合,協助使用者訪問Portal進行配置管理。
二、架構剖析
1、Apollo架構V1
如果不考慮分散式微服務架構中的服務發現問題,Apollo的最簡架構如下圖(來源 楊波)所示:
要點
1、ConfigService是一個獨立的微服務,服務於Client進行配置獲取。
2、Client和ConfigService保持 長連線,通過一種拖拉結合(push & pull)的模式,實現配置實時更新的同時,保證配置更新不丟失。
3、AdminService是一個獨立的微服務,服務於Portal進行配置管理。Portal通過呼叫AdminService進行配置管理和釋出。
4、ConfigService和AdminService共享ConfigDB,ConfigDB中存放專案在某個環境的配置資訊。ConfigService/AdminService/ConfigDB三者在每個環境
(DEV/FAT/UAT/PRO)中都要部署一份。
5、Protal有一個獨立的 PortalDB,存放使用者許可權、專案和配置的後設資料資訊。Protal只需部署一份
,它可以管理多套環境。
2、Apollo架構V2
為了保證高可用,ConfigService和AdminService都是無狀態以叢集方式部署的,這個時候就存在一個服務發現問題:Client怎麼找到ConfigService?Portal
怎麼找到AdminService?為了解決這個問題,Apollo在其架構中引入了Eureka服務註冊中心元件,實現微服務間的服務註冊和發現,更新後的架構如下圖所示:
要點
-
Config/AdminService啟動後都會註冊到Eureka服務註冊中心,並定期傳送保活心跳。
-
Eureka採用叢集方式部署,使用分散式一致性協議保證每個例項的狀態最終一致。
3、Apollo架構V3
我們知道Eureka是自帶服務發現的Java客戶端的,如果Apollo只支援Java客戶端接入,不支援其它語言客戶端接入的話,那麼Client和Portal只需要引入Eureka的Java
客戶端,就可以實現服務發現功能。發現目標服務後,通過客戶端軟負載(SLB,例如Ribbon)就可以路由到目標服務例項。這是一個經典的微服務架構,基於Eureka實現
服務註冊發現+客戶端Ribbon配合實現軟路由,如下圖所示:
4、Apollo架構V4
在攜程,應用場景不僅有Java,還有很多遺留的.Net應用。Apollo的作者也考慮到開源到社群以後,很多客戶應用是非Java的。但是Eureka(包括Ribbon軟負載)原生僅支援
Java客戶端,如果要為多語言開發Eureka/Ribbon客戶端,這個工作量很大也不可控。為此,Apollo的作者引入了MetaServer這個角色,它其實是一個Eureka的Proxy,將
Eureka的服務發現介面以更簡單明確的HTTP介面的形式暴露出來,方便Client/Protal通過簡單的HTTPClient就可以查詢到Config/AdminService的地址列表。獲取到服務
例項地址列表之後,再以簡單的客戶端軟負載(Client SLB)策略路由定位到目標例項,併發起呼叫。
現在還有一個問題,MetaServer本身也是無狀態以叢集方式部署的,那麼Client/Protal該如何發現MetaServer呢?一種傳統的做法是藉助硬體或者軟體負載均衡器,例如在
攜程採用的是擴充套件後的NginxLB(也稱Software Load Balancer),由運維為MetaServer叢集配置一個域名,指向NginxLB叢集,NginxLB再對MetaServer進行負載均衡和
流量轉發。Client/Portal通過域名+NginxLB間接訪問MetaServer叢集。
引入MetaServer和NginxLB之後的架構如下圖所示:
5、Apollo架構V5
V4版本已經是比較完成的Apollo架構全貌,現在還剩下最後一個環節:Portal也是無狀態以叢集方式部署的,使用者如何發現和訪問Portal?答案也是簡單的傳統做法,
使用者通過域名+NginxLB間接訪問MetaServer叢集。
所以V5版本是包括使用者端的最終的Apollo架構全貌,如下圖所示:
6、結論
- 經過我在第三部分的剖析之後,相信大家對Apollo的微服務架構會有更清晰的認識,作為一個思考題,大家再回頭看一下第二部分宋順給出的架構圖,現在是否能夠理解?
它和我的架構是如何對應的?提示一下,宋順的視角是一個從上往下的俯視視角,而我的是一個側面視角。
- ConfgService/AdminService/Client/Portal是Apollo的四個核心微服務模組,相互協作完成配置中心業務功能,Eureka/MetaServer/NginxLB是輔助微服務之間進行服務
發現的模組。
- Apollo採用微服務架構設計,架構和部署都有一些複雜,但是每個服務職責單一,易於擴充套件。另外,Apollo只需要一套Portal就可以集中管理多套環境(DEV/FAT/UAT/PRO)
中的配置,這個是它的架構的一大亮點。。
- 服務發現是微服務架構的基礎,在Apollo的微服務架構中,既採用Eureka註冊中心式的服務發現,也採用NginxLB集中Proxy式的服務發現。
三、可用性考慮
上面設計這麼複雜就是為了滿足高可用,如果不考慮可用性,那麼那麼的v1圖片就可以滿足。我們來下最終的架構圖為什麼能滿足高可用。
很明顯這些模組任何一個掛掉,都能滿足服務的可以用性。
參考
別人罵我胖,我會生氣,因為我心裡承認了我胖。別人說我矮,我就會覺得好笑,因為我心裡知道我不可能矮。這就是我們為什麼會對別人的攻擊生氣。
攻我盾者,乃我內心之矛(27)