假如你使用的是spring-cloud-alibaba微服務(wù)技術(shù)棧
單個服務(wù)獨(dú)有配置文件
即去除應(yīng)用程序的狀態(tài)踏志,配置統(tǒng)一外部化管理,方便進(jìn)行水平的伸縮胀瞪。
集成步驟:
假如我有一個應(yīng)用app-design;
1针余,引入依賴:
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>2.2.1.RELEASE</version>
</dependency>
2, 配置文件饲鄙;
spring.cloud.nacos.config.enabled=true
spring.cloud.nacos.config.refresh-enabled=true
spring.cloud.nacos.config.server-addr=${spring.cloud.nacos.discovery.server-addr}
spring.cloud.nacos.config.namespace=${spring.cloud.nacos.discovery.namespace}
說明如下:
屬性 | 說明 |
---|---|
spring.cloud.nacos.config.server-addr=${spring.cloud.nacos.discovery.server-addr} | nacos配置中心地址 |
spring.cloud.nacos.config.namespace=${spring.cloud.nacos.discovery.namespace} | nacos的命名空間,這里跟服務(wù)發(fā)現(xiàn)的配置一致圆雁; |
3忍级,使用配置的方式,同本地配置文件一樣伪朽。
@Value @PropertyConfiguration 這些注解都是支持的盈咳;
4碰凶,確認(rèn)方式质帅,比如把之前的application.properties的配置放到了配置中心炕檩;
本地啟動的時候,讀取到了8081端口和數(shù)據(jù)庫連接池的配置坚洽;
配置中心的連接原理戈稿,后面單獨(dú)整理出來,知其然并知其所以然讶舰。
服務(wù)之間共享配置文件
場景:多個后端微服務(wù)鞍盗,在同一個集群中共用中間件的配置信息。
比如 緩存redis, 消息隊(duì)列kafka, 文件服務(wù)器跳昼, 郵件服務(wù)器般甲;
那么對應(yīng)的配置文件沒有必要在所有的后端微服務(wù)中單獨(dú)存在,這些配置文件應(yīng)該放在公共配置文件中鹅颊,但是也可以被具體的后端微服務(wù)自己的獨(dú)有配置文件覆蓋敷存,使用自己的私有配置;
可結(jié)合下圖理解:
問題 | 回答 |
---|---|
where are we?現(xiàn)狀 | 中間件配置分散在很多服務(wù)中挪略,配置繁瑣历帚,不方便統(tǒng)一管理 |
where are we go?目的 | 同一個集群的中間件只維護(hù)一份滔岳,各服務(wù)共享杠娱,也可按照需要覆蓋共享的配置; |
how can we go there?實(shí)現(xiàn)路徑 | 基于nacos已有功能實(shí)現(xiàn) |
下面是實(shí)際的coding過程和測試用例谱煤;
服務(wù)app-file;
在服務(wù)對應(yīng)的nacos的namespace中
1 引入共享配置
#共享中間件的配置
spring.cloud.nacos.config.shared-configs[0].data-id=mid.properties
spring.cloud.nacos.config.shared-configs[0].group=DEFAULT_GROUP
spring.cloud.nacos.config.shared-configs[0].refresh=true
位置: 模塊start下的src/main/resources/bootstrap.properties文件中
自描述的配置信息摊求,即引入的共享配置文件列表有哪些,可以按照需要刘离,配置各種中間件的配置信息室叉;
key | 說明 |
---|---|
data-id | _the data id of extended configuration 配置文件名稱,帶上后綴硫惕;翻譯:擴(kuò)展配置文件的數(shù)據(jù)id |
group | _the group of extended configuration, the default value is DEFAULT_GROUP 集群名稱茧痕, 從名字來看,支持多集群的配置文件 翻譯:擴(kuò)展配置文件的集群恼除,默認(rèn)值是 DEFAULT_GROUP |
refresh | _whether to support dynamic refresh, the default does not support 是否刷新 翻譯:是否支持動態(tài)刷新踪旷,默認(rèn)不支持 |
花括號[0] ,里面的0是序號曼氛,如果有多個,按照數(shù)字自增順序進(jìn)行配置令野;
2 在nacos中新增配置文件
根據(jù)實(shí)際場景在nacos的test命名空間中新增配置文件mid.properties
3 獲取配置用例測試
測試接口代碼:
@ApiOperation("測試獲取公共配置文件")
@GetMapping("/config/test")
public Response config(){
String redisConfigServers = environment.getProperty("redis.config.servers","null");
return SingleResponse.of(redisConfigServers);
}
測試用例:
場景 | 期望結(jié)果 | 實(shí)際結(jié)果 | 是否符合預(yù)期 |
---|---|---|---|
獲取共享配置文件中的配置 | r-wz9sp7dhxjnz16bs1jzhutj.redis.rds.aliyuncs.com:6379 | r-wz9sp7dhxjnz16bs1jzhutj.redis.rds.aliyuncs.com:6379 | 是 |
在服務(wù)獨(dú)有app-file.properties配置中重寫配置redis.config.servers=r-wz9sp7dhxjnz16bs1jzhutj.redis.rds.aliyuncs.com:637905 | r-wz9sp7dhxjnz16bs1jzhutj.redis.rds.aliyuncs.com:637905 | r-wz9sp7dhxjnz16bs1jzhutj.redis.rds.aliyuncs.com:637905 | 是 |
截圖如下:
源碼分析
掌握用法之后舀患,深入分析源碼,知其然而知其所以然气破;
starter調(diào)用封裝
使用的starter封裝聊浅;
版本: 2.2.1.RELEASE
啟動的時候自動裝配的配置如下:
org.springframework.cloud.bootstrap.BootstrapConfiguration=\
com.alibaba.cloud.nacos.NacosConfigBootstrapConfiguration
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.alibaba.cloud.nacos.NacosConfigAutoConfiguration,\
com.alibaba.cloud.nacos.endpoint.NacosConfigEndpointAutoConfiguration
org.springframework.boot.diagnostics.FailureAnalyzer=\
com.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureAnalyzer
分解一下key,看一下用途:
key | 說明 |
---|---|
org.springframework.cloud.bootstrap.BootstrapConfiguration | A marker interface used as a key in <code>META-INF/spring.factories</code>. Entries in* the factories file are used to create the bootstrap application context. |
翻譯:一個標(biāo)記注解用來作為key 放在META-INF/spring.factories文件中现使,文件中的條目用來創(chuàng)建啟動應(yīng)用的上下文低匙;
來源:spring-cloud-context-version.jar
value:
com.alibaba.cloud.nacos.NacosConfigBootstrapConfiguration |
| org.springframework.boot.autoconfigure.EnableAutoConfiguration | 注釋太長了,不放這里.放到附錄中碳锈。
來源:spring-boot-autoconfigure-version.jar
com.alibaba.cloud.nacos.NacosConfigAutoConfiguration,\
com.alibaba.cloud.nacos.endpoint.NacosConfigEndpointAutoConfiguration |
| org.springframework.boot.diagnostics.FailureAnalyzer | A {@code FailureAnalyzer} is used to analyze a failure and provide diagnostic* information that can be displayed to the user.
_
翻譯: FailureAnalyzer用來分析錯誤并提供診斷信息展示給到用戶
來源: spring-boot-version.jar
com.alibaba.cloud.nacos.diagnostics.analyzer.NacosConnectionFailureAnalyzer |
然后看看都自動裝配了什么努咐?以及自動裝配的過程。
springboot的方式調(diào)用殴胧;
1 NacosConfigBootstrapConfiguration
源碼:
package com.alibaba.cloud.nacos;
import com.alibaba.cloud.nacos.client.NacosPropertySourceLocator;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @author xiaojing
*/
@Configuration(proxyBeanMethods = false)
@ConditionalOnProperty(name = "spring.cloud.nacos.config.enabled", matchIfMissing = true)
public class NacosConfigBootstrapConfiguration {
@Bean
@ConditionalOnMissingBean
public NacosConfigProperties nacosConfigProperties() {
return new NacosConfigProperties();
}
@Bean
@ConditionalOnMissingBean
public NacosConfigManager nacosConfigManager(
NacosConfigProperties nacosConfigProperties) {
return new NacosConfigManager(nacosConfigProperties);
}
@Bean
public NacosPropertySourceLocator nacosPropertySourceLocator(
NacosConfigManager nacosConfigManager) {
return new NacosPropertySourceLocator(nacosConfigManager);
}
}
自動裝配流程:
配置文件組裝源碼:
@Override
public PropertySource<?> locate(Environment env) {
nacosConfigProperties.setEnvironment(env);
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();
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);
loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env);
return composite;
}
加載應(yīng)用配置文件的順序源碼:
private void loadApplicationConfiguration(
CompositePropertySource compositePropertySource, String dataIdPrefix,
NacosConfigProperties properties, Environment environment) {
String fileExtension = properties.getFileExtension();
String nacosGroup = properties.getGroup();
// load directly once by default
loadNacosDataIfPresent(compositePropertySource, dataIdPrefix, nacosGroup,
fileExtension, true);
// load with suffix, which have a higher priority than the default
loadNacosDataIfPresent(compositePropertySource,
dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension, true);
// Loaded with profile, which have a higher priority than the suffix
for (String profile : environment.getActiveProfiles()) {
String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;
loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,
fileExtension, true);
}
}
順序如下:
序號 | 說明 |
---|---|
1 | 加載dataIdPrefix對應(yīng)的配置文件 |
2 | 加載dataIdPrefix.fileExtension對應(yīng)的配置文件 |
3 | 加載 dataIdPrefix-activeProfiles.fileExtension對應(yīng)的配置文件 |
2.1 NacosConfigAutoConfiguration
序號 | 說明 |
---|---|
1 | NacosConfigProperties nacos配置 |
2 | NacosRefreshProperties 已經(jīng)不建議被使用 |
3 | NacosRefreshHistory 刷新歷史 |
4 | NacosConfigManager 配置 |
5 | NacosContextRefresher 注冊nacos的監(jiān)聽器到應(yīng)用 |
2.2 NacosConfigEndpointAutoConfiguration
NacosConfigEndpoint
本地配置同步邏輯
@ReadOperation
public Map<String, Object> invoke() {
Map<String, Object> result = new HashMap<>(16);
result.put("NacosConfigProperties", properties);
List<NacosPropertySource> all = NacosPropertySourceRepository.getAll();
List<Map<String, Object>> sources = new ArrayList<>();
for (NacosPropertySource ps : all) {
Map<String, Object> source = new HashMap<>(16);
source.put("dataId", ps.getDataId());
source.put("lastSynced", dateFormat.get().format(ps.getTimestamp()));
sources.add(source);
}
result.put("Sources", sources);
result.put("RefreshHistory", refreshHistory.getRecords());
return result;
}
NacosConfigHealthIndicator
健康檢查 UP,DOWN,UNKNOWN ;
3 NacosConnectionFailureAnalyzer
連接不上nacos服務(wù)端拋出異常
@Override
protected FailureAnalysis analyze(Throwable rootFailure,
NacosConnectionFailureException cause) {
return new FailureAnalysis(
"Application failed to connect to Nacos server: \""
+ cause.getServerAddr() + "\"",
"Please check your Nacos server config", cause);
}
小結(jié):服務(wù)通過集成該starter渗稍,通過http請求從nacos的服務(wù)端拉取配置數(shù)據(jù),并做了 配置刷新歷史团滥,注冊監(jiān)聽器到spring容器中竿屹, 本地緩存,和錯誤報告灸姊;
服務(wù)端封裝
源碼位置:https://github.com/alibaba/nacos/tree/develop/config
應(yīng)用啟動讀取配置文件整體調(diào)用鏈:待后續(xù)完成拱燃;
小結(jié)
如果讀完本篇文章你只能記住一句話:nacos作為配置中心可為單獨(dú)的服務(wù)提供外部化配置文件,也支持多應(yīng)用共享配置文件力惯。
從nacos的客戶端源碼分析中可看到一些配置優(yōu)先級的順序碗誉。
原創(chuàng)不易,關(guān)注誠可貴父晶,轉(zhuǎn)發(fā)價更高哮缺!轉(zhuǎn)載請注明出處,讓我們互通有無甲喝,共同進(jìn)步尝苇,歡迎溝通交流。
我會持續(xù)分享Java軟件編程知識和程序員發(fā)展職業(yè)之路埠胖,歡迎關(guān)注糠溜!