- 關(guān)鍵字 :Apollo原理奖亚、Apollo動(dòng)態(tài)刷新機(jī)制
什么是Apollo淳梦?
- Apollo(阿波羅)是攜程框架部門研發(fā)的開源配置管理中心,能夠集中化管理應(yīng)用不同環(huán)境昔字、不同集群的配置爆袍,配置修改后能夠?qū)崟r(shí)推送到應(yīng)用端,并且具備規(guī)范的權(quán)限作郭、流程治理等特性陨囊。
Apollo得原理
-
說起Apollo得原理,不得不引入官方(宋大佬)提供得一張Apollo得設(shè)計(jì)架構(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 會(huì)向其注冊實(shí)例
- 與ConfigService部署在一起
④ Client:客戶端依賴压语,使用方以jar包依賴得方式與服務(wù)端交互
- 與服務(wù)端交互,定時(shí)刷新配置
- 長輪詢實(shí)時(shí)獲取配置
- 實(shí)現(xiàn)客戶端動(dòng)態(tài)刷新功能
⑤ MetaServer:元數(shù)據(jù)服務(wù)集群编检,類似于一個(gè) Eureka得通用代理(屏蔽不同語言得差異)
- 供Portal與Client調(diào)用
⑥ SLB:負(fù)載均衡
- 由于元數(shù)據(jù)服務(wù)是集群胎食,前面需要提供一層負(fù)載均衡策略,然后獲取到Eureka注冊中心得服務(wù)列表蒙谓,再由調(diào)用端發(fā)起服務(wù)請求
配置發(fā)布后的實(shí)時(shí)推送設(shè)計(jì):
大致過程:
① 用戶在Portal操作配置發(fā)布
② Portal調(diào)用Admin Service的接口操作發(fā)布
③ Admin Service發(fā)布配置后斥季,發(fā)送ReleaseMessage給各個(gè)Config Service
④ Config Service收到ReleaseMessage后训桶,通知對(duì)應(yīng)的客戶端
發(fā)送ReleaseMessage的實(shí)現(xiàn)方式
Config Service通知客戶端的實(shí)現(xiàn)方式
客戶端設(shè)計(jì)
實(shí)現(xiàn)原理:
① 客戶端和服務(wù)端保持了一個(gè)長連接累驮,從而能第一時(shí)間獲得配置更新的推送酣倾。(通過Http Long Polling實(shí)現(xiàn))
② 客戶端還會(huì)定時(shí)從Apollo配置中心服務(wù)端拉取應(yīng)用的最新配置。
- 為了防止推送機(jī)制失效導(dǎo)致配置不更新
- 客戶端定時(shí)拉取會(huì)上報(bào)本地版本谤专,所以一般情況下躁锡,對(duì)于定時(shí)拉取的操作,服務(wù)端都會(huì)返回304 - Not Modified
- 默認(rèn)為每5分鐘拉取一次置侍,客戶端也可以通過在運(yùn)行時(shí)指定系統(tǒng)屬性
apollo.refreshInterval
來覆蓋映之,單位為分鐘。 - 客戶端從Apollo配置中心服務(wù)端獲取到應(yīng)用的最新配置后蜡坊,會(huì)保存在內(nèi)存中
- 客戶端會(huì)把從服務(wù)端獲取到的配置在本地文件系統(tǒng)緩存一份(出現(xiàn)網(wǎng)絡(luò)故障時(shí)杠输,依然可以從本地文件恢復(fù)配置)
應(yīng)用程序可以從Apollo客戶端獲取最新的配置、訂閱配置更新通知
和Spring集成的原理
Apollo在Spring環(huán)境下實(shí)現(xiàn)配置優(yōu)先級(jí)原理
應(yīng)用屬性動(dòng)態(tài)刷新原理與示例
-
常用得動(dòng)態(tài)刷新大致分為兩種情況:
① 第一種:
@Value("${test.refresh}")
private String refresh;
此種引入apollo-client客戶端之后秕衙,啟動(dòng)類加上@EnableApolloConfig蠢甲,如果有涉及到屬性發(fā)布,即可刷新
-
原理:就是com.ctrip.framework.apollo.spring.property.SpringValue中會(huì)存一個(gè)弱引用bean据忘,然后收到刷新事件時(shí)鹦牛,直接反射調(diào)用對(duì)應(yīng)的bean設(shè)置值。邏輯在com.ctrip.framework.apollo.spring.config.PropertySourcesProcessor(此處就不一步步源碼分析了勇吊,請讀者參考這幾個(gè)類自己擼一遍源碼)
② 第二種:
@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)聽器针史,重新刷新對(duì)應(yīng)的bean(請讀者自己看一下這幾個(gè)類得實(shí)現(xiàn)就會(huì)一目了然了)
@Value 與 @ConfigurationProperties的動(dòng)態(tài)刷新處理類都是通過DefaultApolloConfigRegistrarHelper注冊的膏燕。
本文大部分原理性得東西都是參考官網(wǎng)來的,有些表達(dá)不明顯得地方作者只是稍加改動(dòng)悟民,作者只是梳理了一下坝辫,便于大家抓重點(diǎn)(因?yàn)楣倬W(wǎng)文檔太多了,文檔很全??)
-
其中示例代碼以及涉及到動(dòng)態(tài)刷新得類是作者自己總結(jié)得射亏,所以如果你不是很了解動(dòng)態(tài)刷新的原理最好還是看一下作者提供得參考類近忙,找一下源碼得位置.
- ? 文章要是勘誤或者知識(shí)點(diǎn)說的不正確,歡迎評(píng)論智润,畢竟這也是作者通過閱讀源碼獲得的知識(shí)及舍,難免會(huì)有疏忽!
- ? 要是感覺文章對(duì)你有所幫助窟绷,不妨點(diǎn)個(gè)關(guān)注锯玛,或者移駕看一下作者的其他文集,也都是干活多多哦,文章也在全力更新中攘残。
- ? 著作權(quán)歸作者所有拙友。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處歼郭!