Spring Cloud Alibaba 整合Nacos Config

前言

前面咱們學習瞭如何在Spring Boot中使用Nacos來管理配置,總體來講仍是比較簡單。web

爲了可以在Spring Cloud中更加方便的使用Nacos,今天介紹下在Spring Cloud中如何簡單,快速,方便的使用Nacos。spring

使用

須要在項目中加入spring-cloud-starter-alibaba-nacos-config的Maven依賴。bootstrap

  
  1. <dependencyManagement>緩存

  2. <dependencies>app

  3. <dependency>ide

  4. <groupId>org.springframework.cloud</groupId>spring-boot

  5. <artifactId>spring-cloud-dependencies</artifactId>學習

  6. <version>Greenwich.SR2</version>測試

  7. <type>pom</type>ui

  8. <scope>import</scope>

  9. </dependency>

  10. <dependency>

  11. <groupId>org.springframework.boot</groupId>

  12. <artifactId>spring-boot-starter-parent</artifactId>

  13. <version>2.1.6.RELEASE</version>

  14. <type>pom</type>

  15. <scope>import</scope>

  16. </dependency>

  17. </dependencies>

  18. </dependencyManagement>

  19. <dependencies>

  20. <dependency>

  21. <groupId>org.springframework.boot</groupId>

  22. <artifactId>spring-boot-starter-web</artifactId>

  23. </dependency>

  24. <dependency>

  25. <groupId>org.springframework.cloud</groupId>

  26. <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>

  27. <version>0.9.0.RELEASE</version>

  28. </dependency>

  29. </dependencies>

<dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>Greenwich.SR2</version> <type>pom</type> <scope>import</scope> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.1.6.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies></dependencyManagement><dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> <version>0.9.0.RELEASE</version> </dependency></dependencies>

版本選擇請參考下面的規範:

因爲 Spring Boot 1 和 Spring Boot 2 在 Actuator 模塊的接口和註解有很大的變動,且 spring-cloud-commons 從 1.x.x 版本升級到 2.0.0 版本也有較大的變動,所以咱們採起跟 SpringBoot 版本號一致的版本:

1.5.x 版本適用於 Spring Boot 1.5.x 2.0.x 版本適用於 Spring Boot 2.0.x 2.1.x 版本適用於 Spring Boot 2.1.x

在bootstrap.properties中配置Nacos的信息,切記是bootstrap.properties不是application.properties,緣由你能夠本身體驗下。

  
  1. # 應用名稱,用於配置文件命名

  2. spring.application.name=example

  3. # Nacos server 的地址

  4. spring.cloud.nacos.config.server-addr=127.0.0.1:8848

  5. # 配置內容的數據格式

  6. spring.cloud.nacos.config.file-extension=properties

  7. # 指定對應的環境

  8. spring.profiles.active=test

# 應用名稱,用於配置文件命名spring.application.name=example# Nacos server 的地址spring.cloud.nacos.config.server-addr=127.0.0.1:8848# 配置內容的數據格式spring.cloud.nacos.config.file-extension=properties# 指定對應的環境spring.profiles.active=test

在 Nacos Spring Cloud 中,dataId 的完整格式以下:

  
  1. ${prefix}-${spring.profile.active}.${file-extension}

${prefix}-${spring.profile.active}.${file-extension}

prefix 默認爲 spring.application.name 的值,也能夠經過配置項 spring.cloud.nacos.config.prefix來配置。

而後咱們在Nacos的後臺建立一個配置,dataId爲example-test.properties

  
  1. useLocalCache=false

useLocalCache=false

再建立一個example-dev.properties

  
  1. useLocalCache=true

useLocalCache=true

測試代碼:

  
  1. @RestController

  2. @RequestMapping("/config")

  3. @RefreshScope

  4. public class ConfigController {

  5. @Value("${useLocalCache:false}")

  6. private boolean useLocalCache;

  7. @RequestMapping("/get")

  8. public boolean get() {

  9. return useLocalCache;

  10. }

  11. }

@RestController@RequestMapping("/config")@RefreshScopepublic class ConfigController { @Value("${useLocalCache:false}") private boolean useLocalCache; @RequestMapping("/get") public boolean get() { return useLocalCache; }}

配置變動須要刷新的話記得加上@RefreshScope註解。加載對應環境的配置是根據spring.profiles.active=test的值進行加載,當咱們指定test後,useLocalCache的值爲false, 當spring.profiles.active=dev時,useLocalCache的值爲true

方便的點在於不用啓動時指定namespace來區分環境,而是跟Spring Boot中的spring.profiles.active進行了整合。這樣的方式仍是隻有默認的namespace,只不過是經過data-id的命名規則來區分環境。

多Data-Id的使用

若是咱們須要加載多個配置文件,能夠用ext-config來配置

  
  1. spring.cloud.nacos.config.ext-config[0].data-id=app.properties

  2. spring.cloud.nacos.config.ext-config[0].group=multi-data-ids

  3. spring.cloud.nacos.config.ext-config[0].refresh=true

  4. spring.cloud.nacos.config.ext-config[1].data-id=user.properties

  5. spring.cloud.nacos.config.ext-config[1].group=multi-data-ids

  6. spring.cloud.nacos.config.ext-config[1].refresh=true

spring.cloud.nacos.config.ext-config[0].data-id=app.propertiesspring.cloud.nacos.config.ext-config[0].group=multi-data-idsspring.cloud.nacos.config.ext-config[0].refresh=truespring.cloud.nacos.config.ext-config[1].data-id=user.propertiesspring.cloud.nacos.config.ext-config[1].group=multi-data-idsspring.cloud.nacos.config.ext-config[1].refresh=true

nacos-config端點

spring-cloud-starter-alibaba-nacos-config內置了nacos-config端點,能夠經過nacos-config端點查看配置相關信息,源碼在org.springframework.cloud.alibaba.nacos.endpoint.NacosConfigEndpoint

  
  1. {

  2. "NacosConfigProperties": {

  3. "serverAddr": "127.0.0.1:8848",

  4. "encode": null,

  5. "group": "DEFAULT_GROUP",

  6. "prefix": null,

  7. "fileExtension": "properties",

  8. "timeout": 3000,

  9. "endpoint": null,

  10. "namespace": null,

  11. "accessKey": null,

  12. "secretKey": null,

  13. "contextPath": null,

  14. "clusterName": null,

  15. "name": null,

  16. "sharedDataids": null,

  17. "refreshableDataids": null,

  18. "extConfig": [

  19. {

  20. "dataId": "example.properties",

  21. "group": "DEFAULT_GROUP",

  22. "refresh": true

  23. },

  24. {

  25. "dataId": "student.properties",

  26. "group": "DEFAULT_GROUP",

  27. "refresh": true

  28. }

  29. ]

  30. },

  31. "RefreshHistory": [],

  32. "Sources": [

  33. {

  34. "lastSynced": "2019-08-18 13:07:42",

  35. "dataId": "student.properties"

  36. },

  37. {

  38. "lastSynced": "2019-08-18 13:07:42",

  39. "dataId": "null-test.properties"

  40. },

  41. {

  42. "lastSynced": "2019-08-18 13:07:42",

  43. "dataId": "null.properties"

  44. },

  45. {

  46. "lastSynced": "2019-08-18 13:07:42",

  47. "dataId": "example.properties"

  48. }

  49. ]

  50. }

{ "NacosConfigProperties": { "serverAddr": "127.0.0.1:8848", "encode": null, "group": "DEFAULT_GROUP", "prefix": null, "fileExtension": "properties", "timeout": 3000, "endpoint": null, "namespace": null, "accessKey": null, "secretKey": null, "contextPath": null, "clusterName": null, "name": null, "sharedDataids": null, "refreshableDataids": null, "extConfig": [ { "dataId": "example.properties", "group": "DEFAULT_GROUP", "refresh": true }, { "dataId": "student.properties", "group": "DEFAULT_GROUP", "refresh": true } ] }, "RefreshHistory": [], "Sources": [ { "lastSynced": "2019-08-18 13:07:42", "dataId": "student.properties" }, { "lastSynced": "2019-08-18 13:07:42", "dataId": "null-test.properties" }, { "lastSynced": "2019-08-18 13:07:42", "dataId": "null.properties" }, { "lastSynced": "2019-08-18 13:07:42", "dataId": "example.properties" } ]}

NacosConfigHealthIndicator

spring-cloud-starter-alibaba-nacos-config內置了Nacos健康狀態檢查的實現,當Nacos出現故障時,可以及時經過actuator/health進行反饋,源碼在org.springframework.cloud.alibaba.nacos.endpoint.NacosConfigHealthIndicator

  
  1. "status": "UP",

  2. "details": {

  3. "diskSpace": {

  4. "status": "UP",

  5. "details": {

  6. "total": 249795969024,

  7. "free": 12436131840,

  8. "threshold": 10485760

  9. }

  10. },

  11. "nacosConfig": {

  12. "status": "UP",

  13. "details": {

  14. "dataId: 'student.properties', group: 'DEFAULT_GROUP'": "config is empty",

  15. "dataId: 'null-test.properties', group: 'DEFAULT_GROUP'": "config is empty",

  16. "dataId: 'null.properties', group: 'DEFAULT_GROUP'": "config is empty",

  17. "dataId: 'example.properties', group: 'DEFAULT_GROUP'": "config is empty",

  18. "dataIds": [

  19. "student.properties",

  20. "null-test.properties",

  21. "null.properties",

  22. "example.properties"

  23. ]

  24. }

  25. },

  26. "refreshScope": {

  27. "status": "UP"

  28. }

  29. }

  30. }

"status": "UP", "details": { "diskSpace": { "status": "UP", "details": { "total": 249795969024, "free": 12436131840, "threshold": 10485760 } }, "nacosConfig": { "status": "UP", "details": { "dataId: 'student.properties', group: 'DEFAULT_GROUP'": "config is empty", "dataId: 'null-test.properties', group: 'DEFAULT_GROUP'": "config is empty", "dataId: 'null.properties', group: 'DEFAULT_GROUP'": "config is empty", "dataId: 'example.properties', group: 'DEFAULT_GROUP'": "config is empty", "dataIds": [ "student.properties", "null-test.properties", "null.properties", "example.properties" ] } }, "refreshScope": { "status": "UP" } }}

目前我本身看下來,感受這塊有那麼一點點問題,現象是Nacos服務所有停掉以後,Nacos的health狀態仍是UP, 並非咱們指望的DOWN。

看了下源碼,發現了緣由,在最後一行設置了UP信息,就算前面設置了DOWN,最後都會變成UP, 不知道這是否是BUG, 哈哈。。。

  
  1. @Override

  2. protected void doHealthCheck(Health.Builder builder) throws Exception {

  3. for (String dataId : dataIds) {

  4. try {

  5. String config = configService.getConfig(dataId,

  6. nacosConfigProperties.getGroup(),

  7. nacosConfigProperties.getTimeout());

  8. if (StringUtils.isEmpty(config)) {

  9. builder.down().withDetail(String.format("dataId: '%s', group: '%s'",

  10. dataId, nacosConfigProperties.getGroup()), "config is empty");

  11. }

  12. }

  13. catch (Exception e) {

  14. builder.down().withDetail(String.format("dataId: '%s', group: '%s'",

  15. dataId, nacosConfigProperties.getGroup()), e.getMessage());

  16. }

  17. }

  18. // 問題出在這邊

  19. builder.up().withDetail("dataIds", dataIds);

  20. }

@Overrideprotected void doHealthCheck(Health.Builder builder) throws Exception { for (String dataId : dataIds) { try { String config = configService.getConfig(dataId, nacosConfigProperties.getGroup(), nacosConfigProperties.getTimeout()); if (StringUtils.isEmpty(config)) { builder.down().withDetail(String.format("dataId: '%s', group: '%s'", dataId, nacosConfigProperties.getGroup()), "config is empty"); } } catch (Exception e) { builder.down().withDetail(String.format("dataId: '%s', group: '%s'", dataId, nacosConfigProperties.getGroup()), e.getMessage()); } } // 問題出在這邊 builder.up().withDetail("dataIds", dataIds);}

我以爲最後一行應該加一個判斷,當前面已經設置DOWN的時候,這邊就不要再設置成UP了

  
  1. if( builder.build().getStatus() != Status.DOWN ) {

  2. builder.up().withDetail("dataIds", dataIds);

  3. }

if( builder.build().getStatus() != Status.DOWN ) { builder.up().withDetail("dataIds", dataIds);}

這邊改完以後,仍是有個問題,就是Nacos其實在本地也有緩存配置信息,固然這個失效時間我沒去看代碼,還不知道多久失效。也就是說當Nacos全部的服務都掛掉後,這邊也不能及時將健康狀態設置成DOWN, 由於configService.getConfig的時候,內部會優先從本地緩存中獲取配置,因此配置是能夠獲取到的,也就是健康檢查在這種狀況下是無效的。

我我的感受健康檢查既然要作的話,那麼就不要走這個邏輯,最簡單的方式每次直接從Nacos服務讀取,讀取異常這個時候就能夠設置成DOWN,就是這麼簡單。

不說了,去Github提個issues問問大佬們....