Apollo配置中心 原理分析

  • 關(guān)鍵字Apollo原理、Apollo動態(tài)刷新機(jī)制

什么是Apollo?

  • Apollo(阿波羅)是攜程框架部門研發(fā)的開源配置管理中心,能夠集中化管理應(yīng)用不同環(huán)境、不同集群的配置,配置修改后能夠?qū)崟r推送到應(yīng)用端,并且具備規(guī)范的權(quán)限流程治理等特性。

Apollo得原理

  • 說起Apollo得原理,不得不引入官方(宋大佬)提供得一張Apollo得設(shè)計架構(gòu)圖:

    Apollo配置中心架構(gòu)圖

    從下往上看依次是:
    ConfigService:配置服務(wù)端,供apollo-client端調(diào)用

    • 提供配置獲取接口:例如:ConfigService.getConfig()
    • 提供配置推送接口( 實(shí)際是基于客戶端得長輪詢,來實(shí)現(xiàn)類似配置推送功能 )

    AdminService:配置Portal,可視化配置得后端服務(wù)

    • 提供配置管理接口
    • 提供配置修改發(fā)布接口

    Eureka:實(shí)現(xiàn)服務(wù)注冊與發(fā)現(xiàn)(為什么選擇Eureka?答案

    • ConfigService/AdminService 會向其注冊實(shí)例
    • 與ConfigService部署在一起

    Client:客戶端依賴,使用方以jar包依賴得方式與服務(wù)端交互

    • 與服務(wù)端交互,定時刷新配置
    • 長輪詢實(shí)時獲取配置
    • 實(shí)現(xiàn)客戶端動態(tài)刷新功能

    MetaServer:元數(shù)據(jù)服務(wù)集群,類似于一個 Eureka得通用代理(屏蔽不同語言得差異)

    • 供Portal與Client調(diào)用

    SLB:負(fù)載均衡

    • 由于元數(shù)據(jù)服務(wù)是集群,前面需要提供一層負(fù)載均衡策略,然后獲取到Eureka注冊中心得服務(wù)列表,再由調(diào)用端發(fā)起服務(wù)請求
配置發(fā)布后的實(shí)時推送設(shè)計:
配置發(fā)布后的實(shí)時推送

大致過程:
① 用戶在Portal操作配置發(fā)布
② Portal調(diào)用Admin Service的接口操作發(fā)布
③ Admin Service發(fā)布配置后,發(fā)送ReleaseMessage給各個Config Service
④ Config Service收到ReleaseMessage后,通知對應(yīng)的客戶端
發(fā)送ReleaseMessage的實(shí)現(xiàn)方式
Config Service通知客戶端的實(shí)現(xiàn)方式

客戶端設(shè)計
客戶端設(shè)計

實(shí)現(xiàn)原理:
① 客戶端和服務(wù)端保持了一個長連接,從而能第一時間獲得配置更新的推送。(通過Http Long Polling實(shí)現(xiàn))
② 客戶端還會定時從Apollo配置中心服務(wù)端拉取應(yīng)用的最新配置。

  • 為了防止推送機(jī)制失效導(dǎo)致配置不更新
  • 客戶端定時拉取會上報本地版本,所以一般情況下,對于定時拉取的操作,服務(wù)端都會返回304 - Not Modified
  • 默認(rèn)為每5分鐘拉取一次,客戶端也可以通過在運(yùn)行時指定系統(tǒng)屬性apollo.refreshInterval來覆蓋,單位為分鐘。
  • 客戶端從Apollo配置中心服務(wù)端獲取到應(yīng)用的最新配置后,會保存在內(nèi)存中
  • 客戶端會把從服務(wù)端獲取到的配置在本地文件系統(tǒng)緩存一份(出現(xiàn)網(wǎng)絡(luò)故障時,依然可以從本地文件恢復(fù)配置)
  • 應(yīng)用程序可以從Apollo客戶端獲取最新的配置、訂閱配置更新通知
和Spring集成的原理

Apollo在Spring環(huán)境下實(shí)現(xiàn)配置優(yōu)先級原理

應(yīng)用屬性動態(tài)刷新原理與示例
  • 常用得動態(tài)刷新大致分為兩種情況:
    ① 第一種:
    @Value("${test.refresh}")
    private String refresh;

此種引入apollo-client客戶端之后,啟動類加上@EnableApolloConfig,如果有涉及到屬性發(fā)布,即可刷新

  • 原理:就是com.ctrip.framework.apollo.spring.property.SpringValue中會存一個弱引用bean,然后收到刷新事件時,直接反射調(diào)用對應(yīng)的bean設(shè)置值。邏輯在com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor(此處就不一步步源碼分析了,請讀者參考這幾個類自己擼一遍源碼)
    ② 第二種:
@Data
@ConfigurationProperties(prefix = "test")
public class DaaSProperties {
    private boolean refresh;
}

以@ConfigurationProperties得形式得屬性,需要額外添加監(jiān)聽器Bean,方法上加上注解@ApolloConfigChangeListener。例如:

    @Configuration
    @Slf4j
    public static class ConfigChangeListener implements ApplicationEventPublisherAware {

        private static ApplicationEventPublisher applicationEventPublisher;

        @ApolloConfigChangeListener(value = "O2O.test.daas")
        private void onChanged(ConfigChangeEvent configChangeEvent){

            Set<String> strings = configChangeEvent.changedKeys();

            strings.forEach( s ->{

                ConfigChange change = configChangeEvent.getChange(s);
                change.getOldValue();

                log.info("【配置變更】Key:{},OldValue:{},NewValue:{}",change.getPropertyName(),change.getOldValue(),change.getNewValue());

            });

            applicationEventPublisher.publishEvent(new EnvironmentChangeEvent(strings));// 刷新ConfigurationProperties Bean
        }

        @Override
        public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {

            ConfigChangeListener.applicationEventPublisher = applicationEventPublisher;
        }
    }
  • 原理:核心在于發(fā)布EnvironmentChangeEvent事件,觸發(fā)ConfigurationPropertiesRebinder監(jiān)聽器,重新刷新對應(yīng)的bean(請讀者自己看一下這幾個類得實(shí)現(xiàn)就會一目了然了)
  • @Value 與 @ConfigurationProperties的動態(tài)刷新處理類都是通過DefaultApolloConfigRegistrarHelper注冊的。
  • 本文大部分原理性得東西都是參考官網(wǎng)來的,有些表達(dá)不明顯得地方作者只是稍加改動,作者只是梳理了一下,便于大家抓重點(diǎn)(因為官網(wǎng)文檔太多了,文檔很全??)

  • 其中示例代碼以及涉及到動態(tài)刷新得類是作者自己總結(jié)得,所以如果你不是很了解動態(tài)刷新的原理最好還是看一下作者提供得參考類,找一下源碼得位置.

    Apollo官網(wǎng)設(shè)計文檔

  1. ? 文章要是勘誤或者知識點(diǎn)說的不正確,歡迎評論,畢竟這也是作者通過閱讀源碼獲得的知識,難免會有疏忽!
  2. ? 要是感覺文章對你有所幫助,不妨點(diǎn)個關(guān)注,或者移駕看一下作者的其他文集,也都是干活多多哦,文章也在全力更新中。
  3. ? 著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處!
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容