Spring Cloud Alibaba Nacos
Nacos 是一个 Alibaba 开源的、易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
使用 Spring Cloud Alibaba Nacos Config,可基于 Spring Cloud 的编程模型快速接入 Nacos 配置管理功能。

1、如何引入 Nacos Config 进行配置管理

如果要在项目中使用 Nacos 来实现配置管理,使用 group ID 为 com.alibaba.cloud 和 artifact ID 为 spring-cloud-starter-alibaba-nacos-config 的 starter。

  1. <dependency>
  2. <groupId>com.alibaba.cloud</groupId>
  3. <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  4. </dependency>

2、快速开始

Nacos Config 使用 DataId 和 GROUP 确定一个配置。配置格式为 Properties 的一个配置项。

2.1. Nacos 服务端初始化

下载编译后压缩包方式

可以从 最新稳定版本 下载 nacos-server-$version.zip 包。
image.png

  1. unzip nacos-server-$version.zip
  2. # 或者
  3. tar -xvf nacos-server-$version.tar.gz
  4. cd nacos/bin

Linux/Unix/Mac启动

启动命令(standalone代表着单机模式运行,非集群模式):

  1. sh startup.sh -m standalone

image.png
如果使用的是ubuntu系统,或者运行脚本报错提示[[符号找不到,可尝试如下运行:

  1. bash startup.sh -m standalone

image.png

Windows启动

启动命令(standalone代表着单机模式运行,非集群模式):

  1. startup.cmd -m standalone

image.png

2.2. Nacos 服务端添加配置

Nacos Server 启动完毕后,访问控制台打印的管理页面的URL,默认的用户名和密码是nacos。
image.png
添加以下配置:

  1. Data ID: nacos-config.properties
  2. Group : DEFAULT_GROUP
  3. 配置格式: Properties
  4. 配置内容: user.name=nacos-config-properties
  5. user.age=90

:::warning 注意DataId是以 properties(默认的文件扩展名方式)为扩展名。 :::

2.3. 客户端使用方式

如果要在项目中使用 Nacos 来实现应用的外部化配置,使用 group ID 为 com.alibaba.cloud 和 artifact ID 为 spring-cloud-starter-alibaba-nacos-config 的 starter。

  1. <dependency>
  2. <groupId>com.alibaba.cloud</groupId>
  3. <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
  4. </dependency>

现在创建一个标准的 Spring Boot 应用。

  1. @SpringBootApplication
  2. public class NacosConfigApplication {
  3. public static void main(String[] args) {
  4. ConfigurableApplicationContext applicationContext = SpringApplication.run(ConfigApplication.class, args);
  5. String userName = applicationContext.getEnvironment().getProperty("user.name");
  6. String userAge = applicationContext.getEnvironment().getProperty("user.age");
  7. System.err.println("user name :"+userName+"; age: "+userAge);
  8. }
  9. }

在运行此 NacosConfigApplication 之前, 必须使用 bootstrap.properties 配置文件来配置 Nacos Server 地址,例如:
bootstrap.properties

  1. # DataId 默认使用 `spring.application.name` 配置跟文件扩展名结合(配置格式默认使用 properties), GROUP 不配置默认使用 DEFAULT_GROUP。因此该配置文件对应的 Nacos Config 配置的 DataId 为 nacos-config.properties, GROUP 为 DEFAULT_GROUP
  2. spring.application.name=nacos-config
  3. spring.cloud.nacos.config.server-addr=127.0.0.1:8848

:::tips 注意当使用域名的方式来访问 Nacos 时,spring.cloud.nacos.config.server-addr 配置的方式为 域名:port。例如 Nacos 的域名为abc.com.nacos,监听的端口为 80,则 spring.cloud.nacos.config.server-addr=abc.com.nacos:80。注意 80 端口不能省略。 ::: 启动这个 Example,可以看到如下输出结果:

  1. 2018-11-02 14:24:51.638 INFO 32700 --- [main] c.a.demo.provider.ConfigApplication : Started ConfigApplication in 14.645 seconds (JVM running for 15.139)
  2. user name :nacos-config-properties; age: 90
  3. 2018-11-02 14:24:51.688 INFO 32700 --- [-127.0.0.1:8848] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@a8c5e74: startup date [Fri Nov 02 14:24:51 CST 2018]; root of context hierarchy

3、基于 DataId 为 yaml 的文件扩展名配置方式

Nacos Config 除了支持 properties 格式以外,也支持 yaml 格式。这个时候只需要完成以下两步:
1、在应用的 bootstrap.properties 配置文件中显示的声明 DataId 文件扩展名。如下所示
bootstrap.properties

  1. spring.cloud.nacos.config.file-extension=yaml

2、在 Nacos 的控制台新增一个DataId为yaml为扩展名的配置,如下所示:

  1. Data ID: nacos-config.yaml
  2. Group : DEFAULT_GROUP
  3. 配置格式: YAML
  4. 配置内容: user.name: nacos-config-yaml
  5. user.age: 68

这两步完成后,重启测试程序,可以看到如下输出结果。

  1. 2018-11-02 14:59:00.484 INFO 32928 --- [main] c.a.demo.provider.ConfigApplication:Started ConfigApplication in 14.183 seconds (JVM running for 14.671)
  2. user name :nacos-config-yaml; age: 68
  3. 2018-11-02 14:59:00.529 INFO 32928 --- [-127.0.0.1:8848] s.c.a.AnnotationConfigApplicationContext : Refreshing org.springframework.context.annotation.AnnotationConfigApplicationContext@265a478e: startup date [Fri Nov 02 14:59:00 CST 2018]; root of context hierarchy

4、支持配置的动态更新

Nacos Config 默认支持配置的动态更新,启动 Spring Boot 应用测试的代码如下:

  1. @SpringBootApplication
  2. public class ConfigApplication {
  3. public static void main(String[] args) {
  4. ConfigurableApplicationContext applicationContext = SpringApplication.run(ConfigApplication.class, args);
  5. while(true) {
  6. //当动态配置刷新时,会更新到 Enviroment中,因此这里每隔一秒中从Enviroment中获取配置
  7. String userName = applicationContext.getEnvironment().getProperty("user.name");
  8. String userAge = applicationContext.getEnvironment().getProperty("user.age");
  9. System.err.println("user name :" + userName + "; age: " + userAge);
  10. TimeUnit.SECONDS.sleep(1);
  11. }
  12. }
  13. }

如下所示,当变更user.name时,应用程序中能够获取到最新的值:

  1. user name :nacos-config-yaml; age: 68
  2. user name :nacos-config-yaml; age: 68
  3. user name :nacos-config-yaml; age: 68
  4. 2018-11-02 15:04:25.069 INFO 32957 --- [-127.0.0.1:8848] o.s.boot.SpringApplication : Started application in 0.144 seconds (JVM running for 71.752)
  5. 2018-11-02 15:04:25.070 INFO 32957 --- [-127.0.0.1:8848] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@10c89124: startup date [Fri Nov 02 15:04:25 CST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@6520af7
  6. 2018-11-02 15:04:25.071 INFO 32957 --- [-127.0.0.1:8848] s.c.a.AnnotationConfigApplicationContext : Closing org.springframework.context.annotation.AnnotationConfigApplicationContext@6520af7: startup date [Fri Nov 02 15:04:24 CST 2018]; root of context hierarchy
  7. //从 Enviroment 中 读取到更改后的值
  8. user name :nacos-config-yaml-update; age: 68
  9. user name :nacos-config-yaml-update; age: 68

:::info 可以通过配置 spring.cloud.nacos.config.refresh.enabled=false 来关闭动态刷新 :::

5、支持profile粒度的配置

Nacos Config 在加载配置的时候,不仅仅加载了以 DataId 为 ${spring.application.name}.${file-extension:properties} 为前缀的基础配置,还加载了DataId为 ${spring.application.name}-${profile}.${file-extension:properties} 的基础配置。在日常开发中如果遇到多套环境下的不同配置,可以通过Spring 提供的 ${spring.profiles.active} 这个配置项来配置。

  1. spring.profiles.active=develop

${spring.profiles.active} 当通过配置文件来指定时必须放在 bootstrap.properties 文件中。
Nacos 上新增一个DataId为:nacos-config-develop.yaml的基础配置,如下所示:

  1. Data ID: nacos-config-develop.yaml
  2. Group : DEFAULT_GROUP
  3. 配置格式: YAML
  4. 配置内容: current.env: develop-env

启动 Spring Boot 应用测试的代码如下:

  1. @SpringBootApplication
  2. public class ConfigApplication {
  3. public static void main(String[] args) {
  4. ConfigurableApplicationContext applicationContext = SpringApplication.run(ConfigApplication.class, args);
  5. while(true) {
  6. String userName = applicationContext.getEnvironment().getProperty("user.name");
  7. String userAge = applicationContext.getEnvironment().getProperty("user.age");
  8. //获取当前部署的环境
  9. String currentEnv = applicationContext.getEnvironment().getProperty("current.env");
  10. System.err.println("in "+currentEnv+" enviroment; "+"user name :" + userName + "; age: " + userAge);
  11. TimeUnit.SECONDS.sleep(1);
  12. }
  13. }
  14. }

启动后,可见控制台的输出结果:

  1. in develop-env enviroment; user name :nacos-config-yaml-update; age: 68
  2. 2018-11-02 15:34:25.013 INFO 33014 --- [ Thread-11] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6f1c29b7: startup date [Fri Nov 02 15:33:57 CST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@63355449

如果需要切换到生产环境,只需要更改 ${spring.profiles.active} 参数配置即可。如下所示:

  1. spring.profiles.active=product

同时生产环境上 Nacos 需要添加对应 DataId 的基础配置。例如,在生成环境下的 Naocs 添加了DataId为:nacos-config-product.yaml的配置:

  1. Data ID: nacos-config-product.yaml
  2. Group : DEFAULT_GROUP
  3. 配置格式: YAML
  4. 配置内容: current.env: product-env

启动测试程序,输出结果如下:

  1. in product-env enviroment; user name :nacos-config-yaml-update; age: 68
  2. 2018-11-02 15:42:14.628 INFO 33024 --- [Thread-11] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@6aa8e115: startup date [Fri Nov 02 15:42:03 CST 2018]; parent: org.springframework.context.annotation.AnnotationConfigApplicationContext@19bb07ed

此案例通过 spring.profiles.active=<profilename> 的方式写死在配置文件中,而在真正的项目实施过程中这个变量的值是需要不同环境而有不同的值。这个时候通常的做法是通过 -Dspring.profiles.active=<profile> 参数指定其配置来达到环境间灵活的切换。

6、支持自定义 namespace 的配置

Nacos 内部有 Namespace 的概念:

用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。

在没有明确指定 ${spring.cloud.nacos.config.namespace} 配置的情况下, 默认使用的是 Nacos 上 Public 这个namespae。如果需要使用自定义的命名空间,可以通过以下配置来实现:

  1. spring.cloud.nacos.config.namespace=b3404bc0-d7dc-4855-b519-570ed34b62d7

该配置必须放在 bootstrap.properties 文件中。此外 spring.cloud.nacos.config.namespace 的值是 namespace 对应的 id,id 值可以在 Nacos 的控制台获取。并且在添加配置时注意不要选择其他的 namespae,否则将会导致读取不到正确的配置。

7、支持自定义 Group 的配置

在没有明确指定 ${spring.cloud.nacos.config.group} 配置的情况下, 默认使用的是 DEFAULT_GROUP 。如果需要自定义自己的 Group,可以通过以下配置来实现:

  1. spring.cloud.nacos.config.group=DEVELOP_GROUP

该配置必须放在 bootstrap.properties 文件中。并且在添加配置时 Group 的值一定要和 spring.cloud.nacos.config.group 的配置值一致。

8、支持自定义扩展的 Data Id 配置

Nacos Config 从 0.2.1 版本后,可支持自定义 Data Id 的配置。关于这部分详细的设计可参考 这里。一个完整的配置案例如下所示:

  1. spring.application.name=opensource-service-provider
  2. spring.cloud.nacos.config.server-addr=127.0.0.1:8848
  3. # config external configuration
  4. # 1、Data Id 在默认的组 DEFAULT_GROUP,不支持配置的动态刷新
  5. spring.cloud.nacos.config.ext-config[0].data-id=ext-config-common01.properties
  6. # 2、Data Id 不在默认的组,不支持动态刷新
  7. spring.cloud.nacos.config.ext-config[1].data-id=ext-config-common02.properties
  8. spring.cloud.nacos.config.ext-config[1].group=GLOBALE_GROUP
  9. # 3、Data Id 既不在默认的组,也支持动态刷新
  10. spring.cloud.nacos.config.ext-config[2].data-id=ext-config-common03.properties
  11. spring.cloud.nacos.config.ext-config[2].group=REFRESH_GROUP
  12. spring.cloud.nacos.config.ext-config[2].refresh=true

可以看到:

  • 通过 spring.cloud.nacos.config.ext-config[n].data-id 的配置方式来支持多个 Data Id 的配置。
  • 通过 spring.cloud.nacos.config.ext-config[n].group 的配置方式自定义 Data Id 所在的组,不明确配置的话,默认是 DEFAULT_GROUP。
  • 通过 spring.cloud.nacos.config.ext-config[n].refresh 的配置方式来控制该 Data Id 在配置变更时,是否支持应用中可动态刷新, 感知到最新的配置值。默认是不支持的。

:::tips 多个 Data Id 同时配置时,他的优先级关系是 spring.cloud.nacos.config.ext-config[n].data-id 其中 n 的值越大,优先级越高。 ::: spring.cloud.nacos.config.ext-config[n].data-id 的值必须带文件扩展名,文件扩展名既可支持 properties,又可以支持 yaml/yml。此时 spring.cloud.nacos.config.file-extension 的配置对自定义扩展配置的 Data Id 文件扩展名没有影响。
通过自定义扩展的 Data Id 配置,既可以解决多个应用间配置共享的问题,又可以支持一个应用有多个配置文件。
为了更加清晰的在多个应用间配置共享的 Data Id ,可以通过以下的方式来配置:

  1. spring.cloud.nacos.config.shared-dataids=bootstrap-common.properties,all-common.properties
  2. spring.cloud.nacos.config.refreshable-dataids=bootstrap-common.properties

可以看到:

  • 通过 spring.cloud.nacos.config.shared-dataids 来支持多个共享 Data Id 的配置,多个之间用逗号隔开。
  • 通过 spring.cloud.nacos.config.refreshable-dataids 来支持哪些共享配置的 Data Id 在配置变化时,应用中是否可动态刷新, 感知到最新的配置值,多个 Data Id 之间用逗号隔开。如果没有明确配置,默认情况下所有共享配置的 Data Id 都不支持动态刷新。 :::info 通过 spring.cloud.nacos.config.shared-dataids 来支持多个共享配置的 Data Id 时, 多个共享配置间的一个优先级的关系约定:按照配置出现的先后顺序,即后面的优先级要高于前面。
    通过 spring.cloud.nacos.config.shared-dataids 来配置时,Data Id 必须带文件扩展名,文件扩展名既可支持 properties,也可以支持 yaml/yml。此时 spring.cloud.nacos.config.file-extension 的配置对自定义扩展配置的 Data Id 文件扩展名没有影响。 ::: spring.cloud.nacos.config.refreshable-dataids 给出哪些需要支持动态刷新时,Data Id 的值也必须明确给出文件扩展名。

    9、配置的优先级

    Nacos Config 目前提供了三种配置能力从 Nacos 拉取相关的配置

  • A: 通过 spring.cloud.nacos.config.shared-dataids 支持多个共享 Data Id 的配置

  • B: 通过 spring.cloud.nacos.config.ext-config[n].data-id 的方式支持多个扩展 Data Id 的配置
  • C: 通过内部相关规则(应用名、应用名+ Profile )自动生成相关的 Data Id 配置

当三种方式共同使用时,他们的一个优先级关系是:A < B < C

10、Nacos Config 对外暴露的 Endpoint

Nacos Config 内部提供了一个 Endpoint, 对应的 endpoint id 为 nacos-config
Endpoint 暴露的 json 中包含了三种属性:

  1. Sources: 当前应用配置的数据信息
  2. RefreshHistory: 配置刷新的历史记录
  3. NacosConfigProperties: 当前应用 Nacos 的基础配置信息

这是 Endpoint 暴露的 json 示例:

  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": "base-common.properties,common.properties",
  17. "refreshableDataids": "common.properties",
  18. "extConfig": null
  19. },
  20. "RefreshHistory": [{
  21. "timestamp": "2019-07-29 11:20:04",
  22. "dataId": "nacos-config-example.properties",
  23. "md5": "7d5d7f1051ff6571e2ec9f90887d9d91"
  24. }],
  25. "Sources": [{
  26. "lastSynced": "2019-07-29 11:19:04",
  27. "dataId": "common.properties"
  28. }, {
  29. "lastSynced": "2019-07-29 11:19:04",
  30. "dataId": "base-common.properties"
  31. }, {
  32. "lastSynced": "2019-07-29 11:19:04",
  33. "dataId": "nacos-config-example.properties"
  34. }]
  35. }

11、完全关闭 Nacos Config 的自动化配置

通过设置 spring.cloud.nacos.config.enabled = false 来完全关闭 Spring Cloud Nacos Config

12、关于 Nacos Config Starter 更多的配置项信息

更多关于 Nacos Config Starter 的配置项如下所示:

配置项 Key 默认值 说明
服务端地址 spring.cloud.nacos.config.server-addr Nacos Server 启动监听的ip地址和端口
配置对应的 DataId spring.cloud.nacos.config.name 先取 prefix,再去 name,最后取 spring.application.name
配置对应的 DataId spring.cloud.nacos.config.prefix 先取 prefix,再去 name,最后取 spring.application.name
配置内容编码 spring.cloud.nacos.config.encode 读取的配置内容对应的编码
GROUP spring.cloud.nacos.config.group DEFAULT_GROUP 配置对应的组
文件扩展名 spring.cloud.nacos.config.fileExtension properties 配置项对应的文件扩展名,目前支持 properties 和 yaml(yml)
获取配置超时时间 spring.cloud.nacos.config.timeout 3000 客户端获取配置的超时时间(毫秒)
接入点 spring.cloud.nacos.config.endpoint 地域的某个服务的入口域名,通过此域名可以动态地拿到服务端地址
命名空间 spring.cloud.nacos.config.namespace 常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等
AccessKey spring.cloud.nacos.config.accessKey 当要上阿里云时,阿里云上面的一个云账号名
SecretKey spring.cloud.nacos.config.secretKey 当要上阿里云时,阿里云上面的一个云账号密码
Nacos Server 对应的 context path spring.cloud.nacos.config.contextPath Nacos Server 对外暴露的 context path
集群 spring.cloud.nacos.config.clusterName 配置成Nacos集群名称
共享配置 spring.cloud.nacos.config.sharedDataids 共享配置的 DataId, “,” 分割
共享配置动态刷新 spring.cloud.nacos.config.refreshableDataids 共享配置中需要动态刷新的 DataId, “,” 分割
自定义 Data Id 配置 spring.cloud.nacos.config.extConfig 属性是个集合,内部由 Config POJO 组成。Config 有 3 个属性,分别是 dataId, group 以及 refresh