Nacos 入门教程 - 配置管理中级篇

上篇 - Nacos 入门教程 - 配置管理(基础篇)

Nacos Config Spring 入门案例

1.0、版本说明

在本案例中,Spring 的版本为 5.2.x,Nacos Server 的版本为 1.4.0,点击下载完整的案例代码。

1.1、发布配置

1
2
3
4
5
Namespace: public
Data ID: nacos_config_spring_demo.properties
Group: DEFAULT_GROUP
配置格式: Properties
配置内容: useLocalCache=true

nacos-config-spring-case-add-configs

1.2 、添加 Maven 依赖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>com.alibaba.nacos</groupId>
<artifactId>nacos-spring-context</artifactId>
<version>1.0.0</version>
</dependency>

1.3、创建 Nacos 配置类

添加 @EnableNacosConfig 注解启用 Nacos Spring 的配置管理服务,其中使用 @NacosPropertySource 加载了 dataId 为 nacos_config_spring_demo.properties 的配置集,并开启自动更新

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package com.nacos.study.config;

import com.alibaba.nacos.api.annotation.NacosProperties;
import com.alibaba.nacos.spring.context.annotation.config.EnableNacosConfig;
import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource;
import org.springframework.context.annotation.Configuration;

/**
* @author clay
*/
@Configuration
@EnableNacosConfig(globalProperties = @NacosProperties(serverAddr = "127.0.0.1:8848"))
@NacosPropertySource(dataId = "nacos_config_spring_demo.properties", autoRefreshed = true)
public class NacosConfiguration {

}

1.4、创建 Controller 测试类

通过 Nacos 的 @NacosValue 注解设置属性值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package com.nacos.study.controller;

import com.alibaba.nacos.api.config.annotation.NacosValue;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;

/**
* @author clay
*/
@Controller
@RequestMapping("/config")
public class ConfigController {

@NacosValue(value = "${useLocalCache:false}", autoRefreshed = true)
private boolean useLocalCache;

@ResponseBody
@RequestMapping(value = "/get", method = RequestMethod.GET)
public boolean get() {
return useLocalCache;
}
}

1.5、配置 web.xml

1
2
3
4
5
6
7
8
9
10
<servlet>
<servlet-name>dispatcherServlet</servlet-name>
<servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<load-on-startup>1</load-on-startup>
</servlet>

<servlet-mapping>
<servlet-name>dispatcherServlet</servlet-name>
<url-pattern>/</url-pattern>
</servlet-mapping>

1.6、配置 dispatcherServlet-servlet.xml

1
2
3
4
5
6
7
<!-- Spring MVC Annotation-Driven -->
<mvc:annotation-driven/>

<!-- Spring Context Annotation-Driven -->
<context:annotation-config/>

<context:component-scan base-package="com.nacos.study"/>

1.7、测试应用程序

    1. 将 Spring Web 应用部署到 Tomcat 服务器
    1. 浏览器访问 http://127.0.0.1:8080/config/get,若响应结果为 true,则说明程序运行正常

Nacos Config Spring Boot 入门案例

2.0、版本说明

在本案例中,Spring Boot 的版本为 2.0.3.RELEASE,对应的 Nacos Config Spring Boot 的版本为 0.2.7,Nacos Server 的版本为 1.4.0,点击下载完整的案例代码。

2.1、发布配置

1
2
3
4
5
Namespace: public
Data ID: nacos_config_springboot_demo.properties
Group: DEFAULT_GROUP
配置格式: Properties
配置内容: useLocalCache=true

nacos-config-springboot-case-add-configs

2.2、添加 Maven 依赖

特别注意,Nacos Spring Boot Starter 版本 0.2.x.RELEASE 对应的是 Spring Boot 2.x 版本,版本 0.1.x.RELEASE 对应的是 Spring Boot 1.x 版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
</parent>

<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<nacos-config-spring-boot.version>0.2.7</nacos-config-spring-boot.version>
</properties>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>${nacos-config-spring-boot.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-actuator</artifactId>
<version>${nacos-config-spring-boot.version}</version>
</dependency>
</dependencies>

2.3、创建启动主类

使用 @NacosPropertySource 加载了 dataId 为 nacos_config_springboot_demo.properties 的配置集,并开启自动更新

1
2
3
4
5
6
7
8
@SpringBootApplication
@NacosPropertySource(dataId = "nacos_config_springboot_demo.properties", autoRefreshed = true)
public class NacosConfigApplication {

public static void main(String[] args) {
SpringApplication.run(NacosConfigApplication.class, args);
}
}

2.4、创建 Controller 测试类

通过 Nacos 的 @NacosValue 注解设置属性值

1
2
3
4
5
6
7
8
9
10
11
12
13
@Controller
@RequestMapping("/config")
public class ConfigController {

@NacosValue(value = "${useLocalCache:false}", autoRefreshed = true)
private boolean useLocalCache;

@ResponseBody
@RequestMapping(value = "/get", method = RequestMethod.GET)
public boolean get() {
return useLocalCache;
}
}

2.5、配置 application.properties

application.properties 中配置 Nacos Server 的地址

1
nacos.config.server-addr=127.0.0.1:8848

2.6、测试应用程序

    1. 启动 Spring Boot 应用
    1. 浏览器访问 http://127.0.0.1:8080/config/get,若响应结果为 true,则说明程序运行正常

Nacos Config Spring Cloud 入门案例

3.0、版本说明

在本案例中,Spring Cloud 的版本是 Greenwich.SR6,对应的 Spring Boot 版本是 2.1.18.RELEASE,对应的 Nacos Config Spring Cloud 版本为 2.1.3.RELEASE,Nacos 官方版本说明可以看这里点击下载完整的案例代码。

3.1、发布配置

第一步:创建名称为 dev 的命名空间

nacos-config-springcloud-case-create-namespace

第二步:在 dev 命名空间下新增两项配置,具体的配置内容如下:

1
2
3
4
5
6
Namespace: 4bfcbae8-8c37-417d-89e4-d5134e23eb18
Data ID: service-1.yaml
Group: TEST_GROUP
配置格式: YAML
配置内容: common:
name: service-1-config
1
2
3
4
5
6
Namespace: 4bfcbae8-8c37-417d-89e4-d5134e23eb18
Data ID: service-2.yaml
Group: TEST_GROUP
配置格式: YAML
配置内容: common:
name: service-2-config

nacos-config-springcloud-case-add-configs

3.2、创建 Maven 父工程

在 Maven 父工程里面配置好工程需要的父级依赖,目的是为了更方便管理与简化配置,具体配置如下。特别注意,Nacos Spring Cloud Starter 版本 2.1.x.RELEASE 对应的是 Spring Boot 2.1.x 版本,版本 2.0.x.RELEASE 对应的是 Spring Boot 2.0.x 版本,版本 1.5.x.RELEASE 对应的是 Spring Boot 1.5.x 版本,Nacos 官方版本说明可以看这里

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.18.RELEASE</version>
</parent>

<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<spring-cloud.version>Greenwich.SR6</spring-cloud.version>
<nacos-config-spring-cloud.version>2.1.3.RELEASE</nacos-config-spring-cloud.version>
</properties>

<!-- 管理依赖 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
<version>${nacos-config-spring-cloud.version}</version>
</dependency>
</dependencies>
</dependencyManagement>

<!-- 利用传递依赖,公共部分 -->
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

3.3、创建 Service 1 工程

创建 Service 1 的 Maven 工程,配置工程里的 pom.xml 文件,需要引入 spring-cloud-starter-alibaba-nacos-config 依赖

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

创建 Service 1 的主启动类

1
2
3
4
5
6
7
@SpringBootApplication
public class Service1Application {

public static void main(String[] args) {
SpringApplication.run(Service1Application.class, args);
}
}

创建 Service 1 的 Controller 测试类,添加 Spring Cloud 原生 @RefreshScope 注解来实现配置自动更新,或者手动通过 ConfigurableApplicationContext.getEnvironment().getProperty() 来实时获取最新的配置信息

1
2
3
4
5
6
7
8
9
10
11
12
13
@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {

@Value("${common.name}")
private String config2;

@GetMapping("/get")
public String get() {
return config2;
}
}

添加 Service 1 需要的 bootstrap.yml 配置文件到工程中

1
2
3
4
5
6
7
8
9
10
11
12
13
server:
port: 56010

spring:
application:
name: service-1
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #配置中心的地址
namespace: 4bfcbae8-8c37-417d-89e4-d5134e23eb18 #命名空间
group: TEST_GROUP #配置分组
file-extension: yaml #由于当前环境对应的profile为空,这里的Data ID的名称就是application的name加上file-extension,即service-1.yaml

3.4、创建 Service 2 工程

创建 Service 2 的 Maven 工程,配置工程里的 pom.xml 文件,需要引入 spring-cloud-starter-alibaba-nacos-config 依赖

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

创建 Service 2 的主启动类

1
2
3
4
5
6
7
@SpringBootApplication
public class Service2Application {

public static void main(String[] args) {
SpringApplication.run(Service2Application.class, args);
}
}

创建 Service 2 的 Controller 测试类,添加 Spring Cloud 原生 @RefreshScope 注解来实现配置自动更新,或者手动通过 ConfigurableApplicationContext.getEnvironment().getProperty() 来实时获取最新的配置信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
@RestController
@RequestMapping("/config")
public class ConfigController {

@Value("${common.name}")
private String config2;

@Autowired
private ConfigurableApplicationContext applicationContext;

@GetMapping("/get")
private String get() {
return config2;
}

@GetMapping("/getRealTime")
private String getRealTime() {
return applicationContext.getEnvironment().getProperty("common.name");
}
}

添加 Service 2 需要的 bootstrap.yml 配置文件到工程中

1
2
3
4
5
6
7
8
9
10
11
12
13
server:
port: 56011

spring:
application:
name: service-2
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #配置中心的地址
namespace: 4bfcbae8-8c37-417d-89e4-d5134e23eb18 #命名空间
group: TEST_GROUP #配置分组
file-extension: yaml #由于当前环境对应的profile为空,这里的Data ID的名称就是application的name加上file-extension,即service-2.yaml

3.5、测试应用程序

    1. 分别启动 nacos-service-1、nacos-service-2 应用
    1. 浏览器访问 http://127.0.0.1:56010/config/get,若响应结果为 service-1-config,则说明 nacos-service-1 应用运行正常
    1. 通过 Nacos 的控制台更改 Data ID 为 service-1.yaml 的配置内容,然后再次访问 http://127.0.0.1:56010/config/get,若响应结果发生了变化,则说明 nacos-service-1 应用可以实时感知到 Nacos Server 的配置变更
    1. 参考步骤二和步骤三,测试 nacos-service-2 应用即可

Nacos Config Spring Cloud 常用配置

常用的配置参数

在上面的 bootstrap.yaml 配置文件中,之所以需要配置 spring.application.name,是因为它是构成 Nacos 配置管理 dataId 字段的一部分,在 Nacos Spring Cloud 中,dataId 的完整格式如下:

1
${prefix}-${spring.profiles.active}.${file-extension}
  • group 默认为 DEFAULT_GROUP,可以通过 spring.cloud.nacos.config.group 来配置
  • prefix 默认为 spring.application.name 的值,也可以通过配置项 spring.cloud.nacos.config.prefix 来配置
  • namespace 默认为 public 命名空间的 ID,可以通过 spring.cloud.nacos.config.namespace 来配置,这里的值是 Namespace 的 ID
  • file-exetension 为配置内容的数据格式,可以通过配置项 spring.cloud.nacos.config.file-extension 来配置,目前只支持 propertiesyaml 类型
  • spring.profiles.active 即为当前环境对应的 profile。特别注意:当 spring.profiles.active 为空时,对应的连接符 - 也将不存在,dataId 的拼接格式会变成 ${prefix}.${file-extension}

完整的配置参数

nacos-spring-cloud-configuration

配置文件加载顺序

若项目中同时存在 bootstrap.yamlapplication.yml 配置文件,那么 Nacos Config Spring Cloud 的配置信息必须写在 bootstrap.yml 配置文件里,因为 Spring Boot 会优先加载 bootstrap.yml 配置文件。值得一提的是,bootstrap.yml 作用于应用程序上下文的引导阶段,bootstrap.yml 由父 Spring ApplicationContext 加载。

自定义 Data ID 配置

自定义扩展 Data ID 配置

在日常项目开发中,单个微服务可能拥有多个配置文件,对应的就是 Nacos 中的多个 Data ID(配置集),例如包括全局配置、局部配置等(如下图),而上面的案例只能使用配置单一的 Data ID(配置集),无法满足实际的开发需求。但 Nacos Config Spring CLoud 提供了自定义扩展 Data ID 的配置,以此来解决该问题。在以下案例中,首先通过 Nacos 的控制台新增了全局配置(extension-config-01.yaml)与默认配置(extension-config-02.yaml),然后在 bootstrap.yaml 配置文件中通过 extension-configs 标签来配置多个 Data ID(配置集),点击下载完整的案例代码。

使用场景

nacos-config-custom-id-scene

发布配置

1
2
3
4
5
6
Namespace: 4bfcbae8-8c37-417d-89e4-d5134e23eb18
Data ID: extension-config-01.yaml
Group: GLOBAL_GROUP
配置格式: YAML
配置内容: common:
address: 127.0.0.1
1
2
3
4
5
6
Namespace: 4bfcbae8-8c37-417d-89e4-d5134e23eb18
Data ID: extension-config-02.yaml
Group: DEFAULT_GROUP
配置格式: YAML
配置内容: common:
threads: 2000

nacos-custom-dataid-add-configs

配置示例

值得一提的是,在旧版 Nacos Config Spring Cloud 中,使用的标签是 ext-config,下标都是从零开始,配置示例如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
server:
port: 56010

spring:
application:
name: service
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #配置中心的地址
namespace: 4bfcbae8-8c37-417d-89e4-d5134e23eb18 #命名空间
extension-configs[0]:
data-id: extension-config-01.yaml
group: GLOBAL_GROUP
refresh: true
extension-configs[1]:
data-id: extension-config-02.yaml
group: DEFAULT_GROUP
refresh: true
  • 通过 spring.cloud.nacos.config.extension-config[n].data-id 的配置方式来支持多个 Data ID 的配置
  • 通过 spring.cloud.nacos.config.extension-config[n].group 的配置方式自定义 Data ID 所在的组,不配置的话,默认是 DEFAULT_GROUP
  • 通过 spring.cloud.nacos.config.extension-config[n].refresh 的配置方式来控制该 Data ID 在配置变更时,是否支持在应用中可动态刷新,感知到最新的配置值,默认是不支持的
  • 多个 Data ID 同时配置时,优先级关系是 spring.cloud.nacos.config.extension-config[n].data-id 其中 n 的值越大,优先级越高
  • spring.cloud.nacos.config.extension-config[n].data-id 的值必须带文件扩展名,文件扩展名支持 propertiesyaml/yml,此时 spring.cloud.nacos.config.file-extension 的配置参数对自定义扩展配置的 Data ID 文件扩展名没有影响

Java 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
@RestController
@RequestMapping("/config")
@RefreshScope
public class ConfigController {

@Value(("${common.address}"))
private String address;

@Value("${common.threads}")
private String threads;

@GetMapping("/get")
public String get() {
return "address: " + address + " threads: " + threads;
}
}

自定义共享 Data ID 配置

为了更加清晰地在多个应用间配置共享的 Data ID,可以使用 spring.cloud.nacos.config.shared-dataids 标签来定义 Data ID。值得一提的是,在新版的 Nacos Config Spring Cloud 中,使用的标签升级为 spring.cloud.nacos.config.shared-configs。当使用自定义共享 Data ID 配置的方式时,只能读取到配置分组(Group)为 DEFAULT_GROUP 的 Data ID,如果 Data ID 归属于其他非默认的配置分组(DEFAULT_GROUP),则无法读取对应的配置信息,所以自定义共享 Data ID 配置的方式在实际开发中使用频率较低。

配置示例

1
2
3
4
5
6
7
8
9
10
11
12
13
server:
port: 56010

spring:
application:
name: service
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848 #配置中心的地址
namespace: 4bfcbae8-8c37-417d-89e4-d5134e23eb18 #命名空间
shared-dataids: shared-config-01.yaml,shared-config-02.yaml
refreshable-dataids: shared-config-01.yaml
  • 通过 spring.cloud.nacos.config.shared-dataids 来支持多个共享 Data ID 的配置,多个之间用逗号隔开
  • 通过 spring.cloud.nacos.config.refreshable-dataids 来支持哪些共享配置的 Data ID 在配置变化时,在应用中是否可动态刷新,感知到最新的配置值,多个 Data ID 之间用逗号隔开。如果没有配置时,默认情况下所有共享配置的 Data ID 都不支持动态刷新
  • 通过 spring.cloud.nacos.config.shared-dataids 来支持多个共享配置的 Data ID 时, 多个共享配置间的优先级关系由配置出现的先后顺序来决定,即后面的优先级要高于前面
  • 通过 spring.cloud.nacos.config.shared-dataids 来配置时,Data ID 必须带文件扩展名,文件扩展名既可支持 propertiesyaml/yml,此时 spring.cloud.nacos.config.file-extension 的配置参数对自定义共享配置的 Data ID 文件扩展名没有影响
  • spring.cloud.nacos.config.refreshable-dataids 配置哪些 Data ID 需要支持动态刷新时,Data ID 的值也必须明确给出文件扩展名

配置加载的优先级

新版的 Nacos Config Spring Cloud 目前提供了三种配置能力从 Nacos 拉取相关的配置,具体如下:

  • A: 通过 spring.cloud.nacos.config.shared-configs 支持多个共享 Data ID 的配置
  • B: 通过 spring.cloud.nacos.config.extension-configs[n].data-id 的方式支持多个扩展 Data ID 的配置
  • C: 通过内部相关规则(应用名 或者 应用名 + Profile),即 ${prefix}-${spring.profiles.active}.${file-extension} 规则来自动生成相关的 Data ID 配置
  • 当三种方式共同使用时,优先级关系是: A < B < C

完全关闭配置

若希望完全关闭 Nacos Config Spring Cloud,可以通过设置 spring.cloud.nacos.config.enabled=false 来关闭。

Nacos Config Spring Cloud 原理浅析

自动注入

Nacos Config Starter 实现了 org.springframework.cloud.bootstrap.config.PropertySourceLocator 接口,并将优先级设置成了最高。在 Spring Cloud 应用启动阶段,会主动从 Nacos Server 端获取对应的数据,并将获取到的数据转换成 PropertySource 且注入到 EnvironmentPropertySources 属性中,所以使用 @Value 注解也能直接获取 Nacos Server 端配置的内容。

动态刷新

Nacos Config Starter 默认为所有获取数据成功的 Nacos 的配置项添加了监听功能,在监听到服务端配置发生变化时会实时触发 org.springframework.cloud.context.refresh.ContextRefresherrefresh() 方法 。如果需要对 Bean 进行动态刷新,给类添加 @RefreshScope@ConfigurationProperties 注解即可。

补充内容

Endpoint 信息查看

Spring Boot 支持这一点,Nacos Config 也可以使用 Endpoint 来暴露信息。在 Maven 中添加 spring-boot-starter-actuator 依赖,并在配置中允许 Endpoints 的访问即可。

  • Spring Boot 1.x 中添加配置 management.security.enabled=false
  • Spring Boot 2.x 中添加配置 management.endpoints.web.exposure.include=*
  • Spring Boot 1.x 可以通过访问 http://127.0.0.1:18084/nacos_config 来查看 Nacos Endpoint 的信息
  • Spring Boot 2.x 可以通过访问 http://127.0.0.1:18084/actuator/nacos-config 来查看 Nacos Endpoint 的信息

下篇 - Nacos 入门教程 - 配置管理(高级篇)