統一配置服務——spring cloud config
前言
近年來,微服務架構的模式越來越受到大眾的追捧。究其緣由,傳統的單體式應用服務一直面臨的問題:業務程式碼臃腫、部署更新繁瑣、語言單一,無法滿足如今網際網路產品業務需求快速變化時快捷、解耦的開發和部署需求。微服務思想,根據業務模組和基礎能力需求,拆分成平級的服務元件,每個元件服務可以採用最適合的語言平臺或者技術架構。
服務分離,解耦了開發和部署,同時,也面臨著亟待解決的問題:服務的配置管理,服務間資料互動等。
統一配置服務
傳統的單體式應用,由於程式碼的高度集中,配置的管理相對比較容易。一般的企業配置會選擇儲存到資料庫,升級部署時只需要修改資料庫連線配置即可,再不濟,由於服務集中,直接修改配置檔案也行。
微服務拆分後,服務變多,部署更新時,挨個服務的去修改配置變得不切實際,不僅效率低,出錯的概率也大。而且,微服務模式之後,資料庫也已經分離,從資料庫讀取配置也變成不可能。所以,需要一種方案來解決這種情況。解決這種情況,無非只需要提供一條所有的微服務都能獲取配置的途徑,這種需求引申出一個基礎能力元件:統一配置服務
spring cloud config
Spring Cloud是一系列框架的有序集合。它利用Spring Boot的開發便利性巧妙地簡化了分散式系統基礎設施的開發,如服務發現註冊、配置中心、訊息匯流排、負載均衡、斷路器、資料監控等,都可以用Spring Boot的開發風格做到一鍵啟動和部署。下面我們要介紹的是其中的配置中心:spring cloud config,以下簡稱configServer。
簡介
統一配置服務分兩部分:提供配置的服務端和提供到服務端獲取配置的客戶端。很容易理解,提供配置的服務端是獨立的微服務,負責從配置庫提取配置提供給其他微服務。供到服務端獲取配置的客戶端,其實就是配置服務提供的工具,幫組微服務從配置服務服務端獲取配置。
構建適合自己的配置服務
關於configServer的使用方法,在這裡我們不作詳細的說明,官網有文件可以參考。我們這裡介紹下如何結合自己目前的專案對configServer進行擴充套件。
configServer目前提供基於git、svn和本地檔案的方式管理配置。基於git和svn的配置管理依賴於git和svn服務,對於需要產品式快速部署場景,不可能為每套環境單獨部署一套git或者svn服務(有人說用公有的git和sv服務,這個需要微服務有外網的訪問許可權,部分政府性質的企業不會允許內部的服務訪問公網)。大多數企業對於自己的專案都有一套配置維護的模式,configServer提供的幾種配置模式不一定能滿足所有的需求,所以,在configServer原有功能基礎上擴充套件一套適用於自己企業的配置管理模式顯得很有必要。
翻看configServer的原始碼可以發現,有個關鍵的介面EnvironmentRepository,根據其命名和提供的方法可以猜出,是用於從配置庫讀取配置的物件。
public interface EnvironmentRepository {
Environment findOne(String application, String profile, String label);
}
configServer通過spring.profiles.active配置選擇配置庫模式,從自動載入配置檔案看,支援native、git、subversion
從上面的程式碼分析,我們需要實現一套從自己的配置庫讀取配置的EnvironmentRepository實現類即可。
基於資料庫儲存配置的例子
下面是基於資料庫配置擴充套件的載入配置的程式碼,@Profile(“db”)表示如果spring.profiles.active=db,將會以擴充套件的資料庫配置模式啟動
public class DbEnvironmentRepositoryConfiguration {
@Configuration
@Profile("db")
protected static class NativeRepositoryConfiguration {
@Autowired
private JdbcTemplate jdbcTemplate;
@Bean
public DbEnvironmentRepository nativeEnvironmentRepository() {
return new DbEnvironmentRepository(jdbcTemplate);
}
}
}
下面是基於資料庫配置實現EnvironmentRepository介面的環境配置庫讀取配置的物件
public class DbEnvironmentRepository implements EnvironmentRepository{
private final static String DEFAULT_VERSION = "1";
private PropertiesStore propertiesStore;
private String version = DEFAULT_VERSION;
public DbEnvironmentRepository(JdbcTemplate jdbcTemplate) {
this.propertiesStore = new DbPropertiesStore(jdbcTemplate);
}
@Override
public Environment findOne(String application, String profile, String label) {
ConfigurableEnvironment environment = getEnvironment(profile);
return fillEnviroment(new PassthruEnvironmentRepository(environment).findOne(application,
profile, label));
}
private ConfigurableEnvironment getEnvironment(String profile) {
ConfigurableEnvironment environment = new StandardEnvironment();
environment.getPropertySources()
.addFirst(new MapPropertySource("profiles",
Collections.<String, Object>singletonMap("spring.profiles.active",
profile)));
return environment;
}
private Environment fillEnviroment(Environment value){
Environment environment = new Environment(value.getName(), value.getProfiles(),
value.getLabel(), this.version, value.getState());
environment.addAll(value.getPropertySources());
environment.addAll(propertiesStore.loadProperties(environment));
return environment;
}
}
啟動後訪問http://localhost:8080/{具體應用的application.name}/default,將會從資料庫讀取指定應用的預設配置資料。
讀取資料庫方面的程式碼沒有提供,可以根據自己的實際環境實現。