Apollo源碼解析看一文就夠 Apollo源碼搭建調試看一文就夠

對於配置中心咱們先拋出問號三連,什麼是配置中心?爲何要用配置中心?配置中心怎麼用?html

筆者說說本身理解的配置中心,我的觀點的十六字java

消息存儲  消息推送  環境隔離  灰度發佈git

今天咱們先來看Apollo配置中心怎麼用,小夥伴可能會說,這不是很簡單嘛,no,咱們同時要來揭開配置保存的實現原理。github

apollo配置都是經過表來保存,那麼咱們來一步一步揭開模型關係。web

看筆者這篇文章的同時,或者你已經熟悉Apollo基本的操做,好比建立集羣、建立Namespace、建立灰度發佈等。若是不熟悉,能夠參考小編上篇文章本身構建Apollo調試環境,參考官方 Apollo使用指南spring

 

建立項目

爲了小夥伴能看的清楚,筆者特地把表數據所有清理了,包括原始項目,項目id是100004458數據庫

那麼咱們先建立一個項目,這個項目能夠匹配咱們本身的服務,好比platform-base-servicejson

這裏解答兩個問題,應用負責人是在管理員工具-用戶管理中配置,對應表是ApolloPortalDB.Usersapi

                          部門是可選項,配置的是ApolloPortalDB.ServerConfig中 organizations對應value,能夠看到筆者這裏配置的造火箭的部門和擰螺絲的部門app

固然能夠在系統工具--管理員參數 配置key=organizations和value=[{"orgId":"TEST1","orgName":"造火箭部門"},{"orgId":"TEST2","orgName":"擰螺絲部門"}]

這裏咱們也能夠擴展一點,

 到此咱們項目已經建立完成。

環境列表

這個看過筆者寫的Apollo源碼搭建調試看一文就夠,應該知道,筆者特地強調了只配置dev環境,也就是ApolloPortalDB.ServerConfig中Key=apollo.portal.envs和Value=dev

這裏再強調一次ApolloPortalDB全部環境只須要部署一個便可,而ApolloConfigDB須要在每一個環境部署一套,如dev、fat、uat和pro分別部署4套ApolloConfigDB。

每一個環境下ApolloConfigDB 配置獨立。這裏也是咱們說到的配置中心須要實現的環境隔離

若是須要配置多環境,按照工程源碼下../apollo/scripts/apollo-on-kubernetes/db下對應環境建立本身的ApolloConfigDB數據度,而後配置apollo.portal.envs,固然也能夠自定義環境。

 

添加集羣 Cluster

集羣使用場景,相似異地多活,同一個項目不用城市獲取的配置項是不一樣的。

  • 經過添加集羣,可使同一份程序在不一樣的集羣(如不一樣的數據中心)使用不一樣的配置
  • 若是不一樣集羣使用同樣的配置,則沒有必要建立集羣

表結構比較簡單,ApolloConfigDB.Cluster表中

 

添加NameSpaces

Apollo在建立項目的時候,都會默認建立一個「application」的Namespace。

對於概念不夠理解,能夠看看官方提供的解釋 Apollo核心概念之「Namespace」

咱們來看看錶數據流向,建立App也是同種方式,數據都是從portal Service到Admin Service。

下面咱們簡單看下ApolloConfigDB中數據模型關係。

總結以下:

一、建立App後,會自動建立默認的Namespace,默認的Cluster,即同時App、Cluster、AppNamespace、Namespace數據。
二、建立Cluster後,Namespace就是關聯AppNamespace和Cluster,即爲每一個 AppNamespace 建立 不一樣集羣的Namespace。

借用官方做者的話,若是把appnamespace比做class的話,namespace就能夠比做是實例化的對象,它在不一樣的環境,不一樣的集羣都有實例。

這裏筆者也有一個疑惑,建立namespace會建立全部環境、全部集羣,具體後面能夠跟蹤下 https://github.com/ctripcorp/apollo/issues/2188

新增配置

這個Item ,配置項,是 Namespace 下最小顆粒度的單位。在 Namespace 分紅五種類型:properties yml yaml json xml

數據存儲在ApolloConfigDB.Item

發佈配置

這裏也是咱們說到的配置中心須要實現的消息推送

這裏也就是全文的重點

服務端實時推送如何設計

 

重點來看看 ReleaseMessage實現方式
一、Admin Service在配置發佈後會往ReleaseMessage表插入一條消息記錄,消息內容就是配置發佈的AppId+Cluster+Namespace,參見 DatabaseMessageSender
二、Apollo.ReleaseMessageScanner線程會每秒掃描一次ReleaseMessage表,看看是否有新的消息記錄,參見 ReleaseMessageScanner
三、Config Service若是發現有新的消息記錄,那麼就會通知到全部的消息監聽器( ReleaseMessageListener),如 NotificationControllerV2,消息監聽器的註冊過程參見 ConfigServiceAutoConfiguration
四、NotificationControllerV2獲得配置發佈的AppId+Cluster+Namespace後,會通知對應的客戶端

Config Service 通知客戶端的實現方式

 

上面有提到其實就是NotificationControllerV2在得知有配置發佈後通知客戶端,實現以下
一、客戶端會發起一個Http請求到Config Service的notifications/v2接口,也就是 NotificationControllerV2,參見 RemoteConfigLongPollService
二、NotificationControllerV2不會當即返回結果,而是經過 Spring DeferredResult把請求掛起
三、若是在60秒內沒有該客戶端關心的配置發佈,那麼會返回Http狀態碼304給客戶端
四、若是有該客戶端關心的配置發佈,NotificationControllerV2會調用DeferredResult的 setResult方法,傳入有配置變化的namespace信息,同時該請求會當即返回。客戶端從返回的結果中獲取到配置變化的namespace後,會當即請求Config Service獲取該namespace的最新配置。

拋出幾個問題:
一、客戶端收到通知消息後,從返回的結果中獲取到配置變化的 namespace 後,會當即請求 Config Service 獲取該 namespace 的最新配置,問題就是爲何不在通知消息中帶過去message,而須要從新獲取?

二、假設一個公共 Namespace 有10W臺機器使用,該公共 Namespace 發佈時直接下發配置更新消息的話,就會致使這 10W 臺機器同時來請求配置,對Config Service的壓力也會特別大如何處理?

實例列表

實例( Instance ),實際就是 Apollo 的客戶端

咱們啓動服務 SpringBootSampleApplication,即啓動了一個Apollo客戶端,能夠查詢到實例列表。
對應咱們的數據庫即ApolloConfigDB.Instance

灰度發佈

這裏也是咱們說到的配置中心須要實現的灰度發佈

咱們能夠理解灰度和分支等價,

  • 建立 Namespace 灰度時:
    • 會建立子 Cluster ,指向父 Cluster 。
    • 會建立子 Namespace ,關聯子 Namespace 。實際上,子 Namespace 和 父 Namespace 無任何數據字段上的關聯。
  • 向子 Namespace 添加 Item 時,該 Item 指向子 Namespace 。雖然,代碼實現和父 Namespace 是如出一轍的。

灰度發佈模型

灰度 Namespace 發佈 Release 。灰度 Namespace 會自動繼承 父 Namespace 已經發布的配置。如有相同的配置項,使用 子 Namespace 的。配置處理的邏輯上,和關聯 Namespace 是一致的。 

 灰度全量發佈

數據庫對應模型

前面咱們已經講了每一個流程操做的數據庫和關係,這裏咱們總結下。

建立項目、集羣、namespace數據關係模型

添加配置項數據關係

發佈配置數據關係

上面操做都設計到日誌審計表ApolloConfigDB.Audit,只是圖這裏沒有表示出來。

 

咱們這裏只聊聊實現原理,具體的操做能夠參考官方灰度發佈指南。若是有任何問題能夠留言一塊兒討論。

相關文章
相關標籤/搜索