程序員你是如何使用Nacos作為配置中心的?


file

假如你使用的是spring-cloud-alibaba微服務技術棧

單個服務獨有配置文件

即去除應用程序的狀態,配置統一外部化管理,方便進行水平的伸縮。

集成步驟:

假如我有一個應用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的命名空間,這里跟服務發現的配置一致;

3,使用配置的方式,同本地配置文件一樣。

@Value @PropertyConfiguration 這些注解都是支持的;

4,確認方式,比如把之前的application.properties的配置放到了配置中心;

image.png

本地啟動的時候,讀取到了8081端口和數據庫連接池的配置;

image.png

配置中心的連接原理,后面單獨整理出來,知其然並知其所以然。

服務之間共享配置文件

場景:多個后端微服務,在同一個集群中共用中間件的配置信息。

比如 緩存redis, 消息隊列kafka, 文件服務器, 郵件服務器;

那么對應的配置文件沒有必要在所有的后端微服務中單獨存在,這些配置文件應該放在公共配置文件中,但是也可以被具體的后端微服務自己的獨有配置文件覆蓋,使用自己的私有配置;

可結合下圖理解:

問題 回答
where are we?現狀 中間件配置分散在很多服務中,配置繁瑣,不方便統一管理
where are we go?目的 同一個集群的中間件只維護一份,各服務共享,也可按照需要覆蓋共享的配置;
how can we go there?實現路徑 基於nacos已有功能實現

下面是實際的coding過程和測試用例;

服務app-file;

在服務對應的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 配置文件名稱,帶上后綴;翻譯:擴展配置文件的數據id
group _the group of extended configuration, the default value is DEFAULT_GROUP 集群名稱, 從名字來看,支持多集群的配置文件 翻譯:擴展配置文件的集群,默認值是 DEFAULT_GROUP
refresh _whether to support dynamic refresh, the default does not support 是否刷新 翻譯:是否支持動態刷新,默認不支持

花括號[0] ,里面的0是序號,如果有多個,按照數字自增順序進行配置;

2 在nacos中新增配置文件

根據實際場景在nacos的test命名空間中新增配置文件mid.properties

image.png

3 獲取配置用例測試

測試接口代碼:

 @ApiOperation("測試獲取公共配置文件")
    @GetMapping("/config/test")
    public Response config(){
        String redisConfigServers = environment.getProperty("redis.config.servers","null");
        return SingleResponse.of(redisConfigServers);
    }

測試用例:

場景 期望結果 實際結果 是否符合預期
獲取共享配置文件中的配置 r-wz9sp7dhxjnz16bs1jzhutj.redis.rds.aliyuncs.com:6379 r-wz9sp7dhxjnz16bs1jzhutj.redis.rds.aliyuncs.com:6379
在服務獨有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

截圖如下:

image.png

image.png

image.png

源碼分析

掌握用法之后,深入分析源碼,知其然而知其所以然;

starter調用封裝

使用的starter封裝;

https://github.com/alibaba/spring-cloud-alibaba/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config

版本: 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 META-INF/spring.factories. Entries in* the factories file are used to create the bootstrap application context.

翻譯:一個標記注解用來作為key 放在META-INF/spring.factories文件中,文件中的條目用來創建啟動應用的上下文;

來源: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的方式調用;

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;
	}

加載應用配置文件的順序源碼:

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對應的配置文件
2 加載dataIdPrefix.fileExtension對應的配置文件
3 加載 dataIdPrefix-activeProfiles.fileExtension對應的配置文件

2.1 NacosConfigAutoConfiguration

序號 說明
1 NacosConfigProperties  nacos配置
2 NacosRefreshProperties  已經不建議被使用
3 NacosRefreshHistory  刷新歷史
4 NacosConfigManager 配置
5 NacosContextRefresher 注冊nacos的監聽器到應用

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服務端拋出異常

@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);
	}

小結:服務通過集成該starter,通過http請求從nacos的服務端拉取配置數據,並做了 配置刷新歷史,注冊監聽器到spring容器中, 本地緩存,和錯誤報告;

服務端封裝

源碼位置:https://github.com/alibaba/nacos/tree/develop/config

應用啟動讀取配置文件整體調用鏈:待后續完成;

小結

如果讀完本篇文章你只能記住一句話:nacos作為配置中心可為單獨的服務提供外部化配置文件,也支持多應用共享配置文件。
從nacos的客戶端源碼分析中可看到一些配置優先級的順序。

原創不易,關注誠可貴,轉發價更高!轉載請注明出處,讓我們互通有無,共同進步,歡迎溝通交流。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM