SpringCloud配置重新整理機制的簡單分析[nacos為例子]
阿新 • • 發佈:2021-01-30
### SpringCloud Nacos
1. 本文主要分為SpringCloud Nacos的設計思路
2. 簡單分析一下觸發重新整理事件後發生的過程以及一些踩坑經驗
#### org.springframework.cloud.bootstrap.config.PropertySourceLocator
1. 這是一個SpringCloud提供的啟動器載入配置類,實現locate,注入到上下文中即可發現配置
```
/**
* @param environment The current Environment.
* @return A PropertySource, or null if there is none.
* @throws IllegalStateException if there is a fail-fast condition.
*/
PropertySource locate(Environment environment);
```
2. com.alibaba.cloud.nacos.client.NacosPropertySourceLocator
- 該類為nacos實現的配置發現類
3. org.springframework.core.env.PropertySource
- 改類為springcloud抽象出來表達屬性源的類
- com.alibaba.cloud.nacos.client.NacosPropertySource / nacos實現了這個類,並賦予了其他屬性
```
/**
* Nacos Group.
*/
private final String group;
/**
* Nacos dataID.
*/
private final String dataId;
/**
* timestamp the property get.
*/
private final Date timestamp;
/**
* Whether to support dynamic refresh for this Property Source.
*/
private final boolean isRefreshable;
```
#### 大概講解com.alibaba.cloud.nacos.client.NacosPropertySourceLocator#locate
1. 原始碼解析
```
@Override
public PropertySource locate(Environment env) {
nacosConfigProperties.setEnvironment(env);
// 獲取nacos配置的服務類,http協議,訪問nacos的api介面獲得配置
ConfigService configService = nacosConfigManager.getConfigService();
if (null == configService) {
log.warn("no instance of config service found, can't load config from nacos");
return null;
}
long timeout = nacosConfigProperties.getTimeout();
// 構建一個builder
nacosPropertySourceBuilder = new NacosPropertySourceBuilder(configService,
timeout);
String name = nacosConfigProperties.getName();
String dataIdPrefix = nacosConfigProperties.getPrefix();
if (StringUtils.isEmpty(dataIdPrefix)) {
dataIdPrefix = name;
}
if (StringUtils.isEmpty(dataIdPrefix)) {
dataIdPrefix = env.getProperty("spring.application.name");
}
// 構建一個複合資料來源
CompositePropertySource composite = new CompositePropertySource(
NACOS_PROPERTY_SOURCE_NAME);
// 載入共享的配置
loadSharedConfiguration(composite);
// 載入擴充套件配置
loadExtConfiguration(composite);
// 載入應用配置,應用配置的優先順序是最高,所以這裡放在最後面來做,是因為新增配置的地方都是addFirst,所以最先的反而優先順序最後
loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env);
return composite;
}
```
2. 每次nacos檢查到配置更新的時候就會觸發上下文配置重新整理,就會調取locate這個方法
#### org.springframework.cloud.endpoint.event.RefreshEvent
1. 該事件為spring cloud內建的事件,用於重新整理配置
#### com.alibaba.cloud.nacos.refresh.NacosRefreshHistory
1. 該類用於nacos刷新歷史的存放,用來儲存每次拉取的配置的md5值,用於比較配置是否需要重新整理
#### com.alibaba.cloud.nacos.refresh.NacosContextRefresher
1. 該類是Nacos用來管理一些內部監聽器的,主要是配置重新整理的時候可以出發回撥,並且發出spring cloud上下文的配置重新整理事件
#### com.alibaba.cloud.nacos.NacosPropertySourceRepository
1. 該類是nacos用來儲存拉取到的資料的
2. 流程:
- 重新整理器檢查到配置更新,儲存到NacosPropertySourceRepository
- 發起重新整理事件
- locate執行,直接讀取NacosPropertySourceRepository
#### com.alibaba.nacos.client.config.NacosConfigService
1. 該類是nacos的主要重新整理配置服務類
2. com.alibaba.nacos.client.config.impl.ClientWorker
- 該類是服務類裡主要的客戶端,協議是HTTP
- clientWorker啟動的時候會初始化2個執行緒池,1個用於定時檢查配置,1個用於輔助檢查
```
executor = Executors.newScheduledThreadPool(1, new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("com.alibaba.nacos.client.Worker." + agent.getName());
t.setDaemon(true);
return t;
}
});
executorService = Executors.newScheduledThreadPool(Runtime.getRuntime().availableProcessors(), new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setName("com.alibaba.nacos.client.Worker.longPolling." + agent.getName());
t.setDaemon(true);
return t;
}
});
executor.scheduleWithFixedDelay(new Runnable() {
@Override
public void run() {
try {
checkConfigInfo();
} catch (Throwable e) {
LOGGER.error("[" + agent.getName() + "] [sub-check] rotate check error", e);
}
}
}, 1L, 10L, TimeUnit.MILLISECONDS);
```
3. com.alibaba.nacos.client.config.impl.ClientWorker.LongPollingRunnable
- 該類用於長輪詢任務
- com.alibaba.nacos.client.config.impl.CacheData#checkListenerMd5比對MD5之後開始重新整理配置
#### com.alibaba.cloud.nacos.parser
1. 該包提供了很多檔案型別的轉換器
2. 載入資料的時候會根據副檔名去查詢一個轉換器例項
```
// com.alibaba.cloud.nacos.client.NacosPropertySourceBuilder#loadNacosData
private Map