spring cloud下用nacos做配置中心的初步探究,替換spring config server
一, 背景:
1, 引入nacos來做配置中心
專案現在用的是spring cloud netflix,沒有用到spring-cloud-alibaba的全家桶,但又想用到nacos來做配置中心,故按官網提供的方式是不行的
2, 探究下nacos配置中心的使用與實現
目前用的spring config server其實弊端很多,比如: 強依賴gitLab, 加入BUS複雜度高不好確保所有節點的更新等缺點
故,想用nacos去替換下當前的配置中心
二, 引入
1, 如何在spring cloud netflix中引入nacos相關?
官網是假設已經引入了spring-cloud-alibaba的,故直接引入
其實都是基於spring-cloud的標準,故直接引入spring cloud alibaba nacos相關適配JAR包即可,但也都有引入spring-cloud-commons,需要主要版本的適配
<!-- https://mvnrepository.com/artifact/org.springframework.cloud/spring-cloud-starter-alibaba-nacos-config --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>0.1.1.RELEASE</version> </dependency>
然後在bootstrap.yml中加入相關配置,如
spring:
cloud:
nacos:
config:
server-addr: 10.1.5.101:8848
然後和官網一樣了, 預設的dataId是
${spring.application.name}-${spring.profile.active}.${file-extension}
其中 file-extension 預設為 properties
如,專案名為 test
那麼active為local的預設dataId為
test-local.properties
三, nacos的使用
哪些配置可以熱更新
這裡其實和config server的用法一樣,也是實現了spring cloud config的標準
1), spring boot 的 自動裝配模式的可以直接熱更新
如:
@ConfigurationProperties(PREFIX)
public class TestSentinelConfig {
public static final String PREFIX = "test.sentinel";
private String values;
public String getValues() {
return values;
}
public void setValues(String values) {
this.values = values;
}
}
2) , 加了作用域@RefreshScope的,如: @Value("${value}")模式注入的話,需要在bean上加入RefreshScope標籤
@RefreshScope
@RestController
public class TestOnly {
@Value("${testConfig.value1}")
private String value;
@RequestMapping("test/test")
public String test() {
return value;
}
}
四,實現原理探究
nacos是通過長輪詢,拉取最新配置的,拉去到最新配置後,在spring 的context裡進行事件釋出一個RefreshEvent。
輪詢釋出事件具體原始碼:
入口, nacos client 中
ClientWorker ->
executor.scheduleWithFixedDelay(new Runnable() {
public void run() {
try {
checkConfigInfo();
} catch (Throwable e) {
log.error(agent.getName(), "NACOS-XXXX", "[sub-check] rotate check error", e);
}
}
}, 1L, 10L, TimeUnit.MILLISECONDS);
10L一次 執行一次checkConfigInfo()
然後nacos的spring cloud的介面卡,spring-cloud-starter-alibaba-nacos-config進行適配
遇到更新便釋出RefreshEvent #org.springframework.cloud.alibaba.nacos.refresh.NacosContextRefresher$1.receiveConfigInfo
...
refreshHistory.add(dataId, md5);
applicationContext.publishEvent(
new RefreshEvent(this, null, "Refresh Nacos config"));
....
這部分 更多spring cloud alibaba nacos原始碼細節實現
再往後,就是spring cloud context本身的實現了,這部分和spring config server是一樣的了
然後後續就和spring config server的一樣了
org.springframework.cloud.endpoint.event.RefreshEventListener 監聽 -->
核心部分 ContextRefresher#refresh()
public synchronized Set<String> refresh() {
Map<String, Object> before = extract(
this.context.getEnvironment().getPropertySources());
addConfigFilesToEnvironment();
Set<String> keys = changes(before,
extract(this.context.getEnvironment().getPropertySources())).keySet();
this.context.publishEvent(new EnvironmentChangeEvent(keys));
this.scope.refreshAll();
return keys;
}
這部分網上分析的資料就比較多了,和原來我們用spring config server 訪問refresh其實是一個意識了
這部分簡單說就是nacos client長輪詢dataId的修改,然後通知到spring cloud alibaba的介面卡,通過spring cloud common部分進行熱更新屬性。
五,遺留問題
1, 這部分叢集的策略還得探究
2, 對於配置資訊的資料庫的持久化還沒加上
3,如何替代spring config server的版本控制策略,用group麼
4,是否要用到nacos的註冊中心去替