Disconf實踐指南:改造篇
上一篇文章Disconf實踐指南:使用篇介紹瞭如何在專案中應用disconf,雖然實現了分散式配置的實時重新整理,但是我們希望能夠去除所有的配置檔案,把配置都交給disconf管理,本地只需要實現配置監聽介面就好了。
改造包括:
統一配置到disconf
自定義配置解析實現
公共配置 #實現ing
1、統一配置到disconf
主要是應用各個環境的配置資訊,比如當前應用的配置資訊application-default.properties如下:
env=dev
spring.application .name=springboot-learning-example
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp
server.port=9999
logging.path=/Users/chubin/logs
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
在disconf控制檯新建配置檔案,命名為app.properties,同時將本地application-default.properties檔案刪除,重新啟動應用,如果啟動成功說明配置生效了。那麼為什麼不用像之前redis.properties一樣本地建立監聽檔案呢?注意到disconf.xml配置檔案中有如下的配置:
其中的location屬性就表示app.properties這個檔案disconf會幫你託管,專案啟動或者配置更新的時候會自動reload到本地,實時重新整理。這裡有一個關鍵的類ReloadablePropertiesFactoryBean
,它是真正實現配置更新的核心,實現了配置更新回撥並設定新的value。
如果還有其他環境的配置資訊,都可以遷移到disconf,區別在於選擇的環境不一樣。這樣我們就將本地的應用配置遷移到了disconf。
2、自定義配置解析
在分散式系統中,為了實現程式碼不同的邏輯分支,比如灰度可以需要灰度釋出的城市,沒有開啟灰度的城市走老邏輯,開啟灰度的城市走新邏輯。這種情況下就需要使用分散式配置動態修改了。
之前的redis.properties已經實現了動態更新和實時生效,但是缺點是需要本地實現更新服務介面並且新增redis.properties的key作為更新服務的屬性,那麼可不可以只實現更新介面卻不需要新增配置的key作為屬性呢?當然是可以的。通過實現IDisconfUpdatePipeline
介面自定義配置的解析方式。
該介面需要實現reloadDisconfFile方法,入參是key和filePath,key表示配置檔案的名稱,如果應用有多個配置檔案,那麼修改其中一個檔案的配置時,其他配置也會reload到本地,所以需要對關心的配置檔案執行reload自定義解析。
一種思路是在ReloadablePropertiesFactoryBean
中將配置設定到spring的environment環境變數中,然後配置更新的時候直接從環境變數直接獲取就可以了。修改原始碼如下:
Environment environment = applicationContext.getEnvironment();
ConfigurableEnvironment env = (ConfigurableEnvironment) environment;
env.getPropertySources().addFirst(
new PropertiesPropertySource("springboot-demo", properties));
log.debug("inject properties to env:{}", properties);
- 1
- 2
- 3
- 4
- 5
所以reloadDisconfFile方法可以如下實現:
Map<String, Object> cacheMap = new HashMap<>();
PropertySource<?> propertySource = env.getPropertySources().get("springboot-demo");
if (propertySource instanceof PropertiesPropertySource) {
PropertiesPropertySource propertiesPropertySource = (PropertiesPropertySource) propertySource;
Map<String, Object> objectMap = propertiesPropertySource.getSource();
for (Map.Entry<String, Object> e : objectMap.entrySet()) {
cacheMap.put(e.getKey(), e.getValue());
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
這樣就將disconf的配置封裝成了一個Map,要獲取某個值直接去get就可以獲取到了,相比之前的一坨配置是不是簡化了很多。
至此,終於可以愉快的使用disconf了。
上一篇文章Disconf實踐指南:使用篇介紹瞭如何在專案中應用disconf,雖然實現了分散式配置的實時重新整理,但是我們希望能夠去除所有的配置檔案,把配置都交給disconf管理,本地只需要實現配置監聽介面就好了。