- 關(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í)現(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)刷新的原理最好還是看一下作者提供得參考類,找一下源碼得位置.
- ? 文章要是勘誤或者知識點(diǎn)說的不正確,歡迎評論,畢竟這也是作者通過閱讀源碼獲得的知識,難免會有疏忽!
- ? 要是感覺文章對你有所幫助,不妨點(diǎn)個關(guān)注,或者移駕看一下作者的其他文集,也都是干活多多哦,文章也在全力更新中。
- ? 著作權(quán)歸作者所有。商業(yè)轉(zhuǎn)載請聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請注明出處!