1. 程式人生 > >程式設計師你是如何使用Nacos作為配置中心的?

程式設計師你是如何使用Nacos作為配置中心的?

![file](https://img2020.cnblogs.com/other/268922/202010/268922-20201009234957286-366094551.jpg) > 假如你使用的是spring-cloud-alibaba微服務技術棧 # 單個服務獨有配置檔案 即去除應用程式的狀態,配置統一外部化管理,方便進行水平的伸縮。 整合步驟: 假如我有一個應用app-design; 1,引入依賴: ```xml com.alibaba.cloud spring-cloud-starter-alibaba-nacos-config 2.2.1.RELEASE ``` 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](https://img2020.cnblogs.com/other/268922/202010/268922-20201009234957697-1783037964.png) 本地啟動的時候,讀取到了8081埠和資料庫連線池的配置; ![image.png](https://img2020.cnblogs.com/other/268922/202010/268922-20201009235006569-1599946998.png) 配置中心的連線原理,後面單獨整理出來,知其然並知其所以然。 # 服務之間共享配置檔案 場景:多個後端微服務,在同一個叢集中共用中介軟體的配置資訊。 比如 快取redis, 訊息佇列kafka, 檔案伺服器, 郵件伺服器; 那麼對應的配置檔案沒有必要在所有的後端微服務中單獨存在,這些配置檔案應該放在公共配置檔案中,但是也可以被具體的後端微服務自己的獨有配置檔案覆蓋,使用自己的私有配置; 可結合下圖理解: ![](https://img2020.cnblogs.com/other/268922/202010/268922-20201009235007691-1654129973.svg+xml) | 問題 | 回答 | | --- | --- | | 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](https://img2020.cnblogs.com/other/268922/202010/268922-20201009235008032-1384534892.png) ## 3 獲取配置用例測試 測試介面程式碼: ```java @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](https://img2020.cnblogs.com/other/268922/202010/268922-20201009235008398-1947104286.png) ![image.png](https://img2020.cnblogs.com/other/268922/202010/268922-20201009235008674-698714325.png) ![image.png](https://img2020.cnblogs.com/other/268922/202010/268922-20201009235008921-604219324.png) # 原始碼分析 掌握用法之後,深入分析原始碼,知其然而知其所以然; ## starter呼叫封裝 使用的starter封裝; [https://github.com/alibaba/spring-cloud-alibaba/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config](https://github.com/alibaba/spring-cloud-alibaba/spring-cloud-alibaba-starters/spring-cloud-starter-alibaba-nacos-config) 版本: 2.2.1.RELEASE 啟動的時候自動裝配的配置如下: ```java 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 原始碼: ```java 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); } } ``` 自動裝配流程: ![](https://img2020.cnblogs.com/other/268922/202010/268922-20201009235009216-1421201079.svg+xml) 配置檔案組裝原始碼: ```java @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; } ``` ![](https://img2020.cnblogs.com/other/268922/202010/268922-20201009235009387-2622454.svg+xml) 載入應用配置檔案的順序原始碼: ```java 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 本地配置同步邏輯 ```java @ReadOperation public Map invoke() { Map result = new HashMap<>(16); result.put("NacosConfigProperties", properties); List all = NacosPropertySourceRepository.getAll(); List> sources = new ArrayList<>(); for (NacosPropertySource ps : all) { Map 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服務端丟擲異常 ```java @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](https://github.com/alibaba/nacos/tree/develop/config) 應用啟動讀取配置檔案整體呼叫鏈:待後續完成; # 小結 >如果讀完本篇文章你只能記住一句話:nacos作為配置中心可為單獨的服務提供外部化配置檔案,也支援多應用共享配置檔案。 >從nacos的客戶端原始碼分析中可看到一些配置優先順序的順序。 > 原創不易,關注誠可貴,轉發價更高!轉載請註明出處,讓我們互通有無,共同進步,歡迎溝通