1. 程式人生 > >Disconf實踐指南:改造篇

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配置檔案中有如下的配置:

disconf配置

其中的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管理,本地只需要實現配置監聽介面就好了。