43.Spring Boot 配置中心 Nacos 入门
43.Spring Boot 配置中心 Nacos 入门
1. 概述
在《Nacos 极简入门》中,我们已经学习了如何搭建一个 Nacos 服务。如果还没有的胖友,赶紧先去简单学习下,重点是跟着该文「2. 单机部署」小节,自己搭建一个 Nacos 服务。
本文,我们来学习下如何在 Spring Boot 中,将 Nacos 作为一个配置中心,实现分布式环境下的配置管理。
友情提示:对 Nacos 作为注册中心感兴趣的胖友,可以看看《芋道 Spring Boot 注册中心 Nacos 入门》文章。
2. 快速入门
示例代码对应仓库:lab-44-nacos-config-demo。
本小节,我们会在 Nacos 服务中定义配置,并使用 @ConfigurationProperties
和 @Value
注解,读取该配置。
友情提示:如果胖友看过《Spring Boot 配置文件入门》的「2. 自定义配置」小节,就会发现本小节是对标这块的内容。
如果没看过,也没关系,艿艿只是提一下而已,嘿嘿。继续往下看即可。
2.1 引入依赖
在 pom.xml
文件中,引入相关依赖。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lab-44-nacos-config-demo</artifactId>
<dependencies>
<!-- Spring Boot Starter 基础依赖 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<!-- 实现对 Nacos 作为配置中心的自动化配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.4</version>
</dependency>
</dependencies>
</project>
- 重点是引入
nacos-config-spring-boot-starter
依赖,实现对 Nacos 作为配置中心的自动化配置。
2.2 配置文件
在 application.yml
中,添加 Nacos 配置,如下:
nacos:
# Nacos 配置中心的配置项,对应 NacosConfigProperties 配置类
config:
server-addr: 127.0.0.1:18848 # Nacos 服务器地址
bootstrap:
enable: true # 是否开启 Nacos 配置预加载功能。默认为 false。
log-enable: true # 是否开启 Nacos 支持日志级别的加载时机。默认为 false。
data-id: example # 使用的 Nacos 配置集的 dataId。
type: YAML # 使用的 Nacos 配置集的配置格式。默认为 PROPERTIES。
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP。
namespace: # 使用的 Nacos 的命名空间,默认为 null。
nacos.config
配置项,为 Nacos 作为配置中心的配置,对应 NacosConfigProperties 配置类。
server-addr
:Nacos 服务器地址。bootstrap.enable
:是否开启 Nacos 配置预加载功能。默认为false
。😈 这里,我们设置为true
,保证使用@Value
和@ConfigurationProperties
注解,可以读取到来自 Nacos 的配置项。bootstrap.log-enable
:是否开启 Nacos 支持日志级别的加载时机。默认为false
。😈 这里,我们设置为true
,保证 Spring Boot 应用的 Logger 能够使用来自 Nacos 的配置项。data-id
:使用的 Nacos 配置集的 dataId。😈 这里,我们设置为example
,稍后会去创建。FROM 《Nacos 文档 ------ Nacos 概念》
配置集
一组相关或者不相关的配置项的集合称为配置集。在系统中,一个配置文件通常就是一个配置集,包含了系统各个方面的配置。例如,一个配置集可能包含了数据源、线程池、日志级别等配置项。配置集 ID
Nacos 中的某个配置集的 ID。配置集 ID 是组织划分配置的维度之一。Data ID 通常用于组织划分系统的配置集。一个系统或者应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识。Data ID 通常采用类 Java 包(如com.taobao.tc.refund.log.level
)的命名规则保证全局唯一性。此命名规则非强制。type
:使用的 Nacos 配置集的配置格式。默认为PROPERTIES
。这里,我们设置YAML
,对应 YAML 格式的配置格式。group
:使用的 Nacos 配置分组,默认为DEFAULT_GROUP
。😈 这里,我们设置为DEFAULT_GROUP
,就是默认值。FROM 《Nacos 文档 ------ Nacos 概念》
配置分组
Nacos 中的一组配置集,是组织配置的维度之一。通过一个有意义的字符串(如 Buy 或 Trade )对配置集进行分组,从而区分 Data ID 相同的配置集。当您在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用DEFAULT_GROUP
。配置分组的常见场景:不同的应用或组件使用了相同的配置类型,如database_url
配置和MQ_topic
配置。namespace
:使用的 Nacos 的命名空间,默认为null
。😈 稍后,我们会通过namespace
配置项,基于 Nacos 的多环境不同配置的功能。FROM 《Nacos 文档 ------ Nacos 概念》
命名空间
用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
😜 突然看到 Nacos 一大片的概念,胖友会有点懵逼。问题不大,跟着示例继续往下,会逐步有感觉的。
更多 Nacos Config Spring Boot 配置项,可以看看《nacos-spring-boot-project ------ WIKI》文章。
2.3 创建 Nacos 配置集
① 打开 Nacos UI 界面的「配置列表」菜单,进入「配置管理」功能。如下图所示:
② 点击列表右上角的➕号,进入「新建配置」界面,创建一个 Nacos 配置集。输入如下内容,并点击「发布」按钮,完成创建。如下图所示:
其中,YAML 配置文件如下:
order:
pay-timeout-seconds: 120 # 订单支付超时时长,单位:秒。
create-frequency-seconds: 10 # 订单创建频率,单位:秒
2.4 OrderProperties
创建 OrderProperties 配置类,读取 order
配置项。代码如下:
@Component
@ConfigurationProperties(prefix = "order")
// @NacosConfigurationProperties(prefix = "order", dataId = "${nacos.config.data-id}", type = ConfigType.YAML)
public class OrderProperties {
/**
* 订单支付超时时长,单位:秒。
*/
private Integer payTimeoutSeconds;
/**
* 订单创建频率,单位:秒
*/
private Integer createFrequencySeconds;
// ... 省略 set/get 方法
}
- 在类上,添加
@Component
注解,保证该配置类可以作为一个 Bean 被扫描到。 - 在类上,添加
@ConfigurationProperties
注解,并设置prefix = "order"
属性,这样它就可以读取前缀 为order
配置项,设置到配置类对应的属性上。
😈 这里,我们注释了一段 @NacosConfigurationProperties
注解的代码,该注解在功能上是对标 @ConfigurationProperties
注解,用于将 Nacos 配置注入 POJO 配置类中。为什么我们这里注释掉了呢?因为我们在「2.2 配置文件」中,设置了 nacos.config.bootstrap.enable=true
,Spring Boot 应用在启动时,预加载了来自 Nacos 配置,所以可以直接使用 @ConfigurationProperties
注解即可。这样的好处,是可以更加通用,而无需和 Nacos 有耦合与依赖。
2.5 Application
创建 Application.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication
// @NacosPropertySource(dataId = "example", type = ConfigType.YAML)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
@Component
public class OrderPropertiesCommandLineRunner implements CommandLineRunner {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private OrderProperties orderProperties;
@Override
public void run(String... args) {
logger.info("payTimeoutSeconds:" + orderProperties.getPayTimeoutSeconds());
logger.info("createFrequencySeconds:" + orderProperties.getCreateFrequencySeconds());
}
}
@Component
public class ValueCommandLineRunner implements CommandLineRunner {
private final Logger logger = LoggerFactory.getLogger(getClass());
// @NacosValue(value = "${order.pay-timeout-seconds}")
@Value(value = "${order.pay-timeout-seconds}")
private Integer payTimeoutSeconds;
// @NacosValue(value = "${order.create-frequency-seconds}")
@Value(value = "${order.create-frequency-seconds}")
private Integer createFrequencySeconds;
@Override
public void run(String... args) {
logger.info("payTimeoutSeconds:" + payTimeoutSeconds);
logger.info("createFrequencySeconds:" + createFrequencySeconds);
}
}
}
① 在 Application 类上,我们注释了一段 @NacosPropertySource
注解,该注解用于声明从 Nacos 读取的配置集。为什么我们整列注释掉了呢?因为我们在「2.2 配置文件」中,通过 nacos.config.data-id
、nacos.config.type
等配置项,已经设置从 Nacos 读取的配置集。该配置一般用于在纯 Spring 应用中,使用 Nacos 作为配置中心。
② 在 OrderPropertiesCommandLineRunner 类中,我们测试了使用 @ConfigurationProperties
注解的 OrderProperties 配置类,读取 order
配置项的效果。
③ 在 ValueCommandLineRunner 类中,我们测试了使用 @Value
注解,读取 order
配置项的效果。😈 这里,我们注释了一段 @NacosValue
注解的代码,该注解在功能上是对标 @Value
注解,用于将 Nacos 配置注入属性种。为什么我们这里注释掉了呢?原因同 @NacosConfigurationProperties
注解。
友情提示:
@Value
注解,是 Spring 所提供。@ConfigurationProperties
注解,是 Spring Boot 所提供。
下面,我们来执行 Application 的 #main(String[] args)
方法,启动 Spring Boot 应用。输出日志如下:
# 从 Nacos 中,读取 example 配置集。
2020-01-22 11:49:11.679 INFO 8430 --- [ main] c.a.b.n.c.u.NacosConfigPropertiesUtils : nacosConfigProperties : com.alibaba.boot.nacos.config.properties.NacosConfigProperties@6ff29830
2020-01-22 11:49:12.018 INFO 8430 --- [ main] c.a.b.n.config.util.NacosConfigUtils : load config from nacos, data-id is : example, group is : DEFAULT_GROUP
# ValueCommandLineRunner 输出
2020-01-22 11:49:12.745 INFO 8430 --- [ main] s.l.n.Application$ValueCommandLineRunner : payTimeoutSeconds:120
2020-01-22 11:49:12.746 INFO 8430 --- [ main] s.l.n.Application$ValueCommandLineRunner : createFrequencySeconds:120
# OrderPropertiesCommandLineRunner 输出
2020-01-22 11:49:12.746 INFO 8430 --- [ main] ication$OrderPropertiesCommandLineRunner : payTimeoutSeconds:120
2020-01-22 11:49:12.746 INFO 8430 --- [ main] ication$OrderPropertiesCommandLineRunner : createFrequencySeconds:10
- 两个 CommandLineRunner 都读取
order
配置项成功,美滋滋。
友情提示:艿艿自己尝试了在《芋道 Spring Boot 配置文件入门》的如下小节的功能,都可以完美支持:
3. 多环境配置
示例代码对应仓库:lab-44-nacos-config-demo-profiles。
在《芋道 Spring Boot 配置文件入门》的「6. 多环境配置」中,我们介绍如何基于 spring.profiles.active
配置项,在 Spring Boot 实现多环境的配置功能。在本小节中,我们会在该基础之上,实现结合 Nacos 的多环境配置。
实际上,Nacos 开发者已经告诉我们如何实现了,通过 Nacos namespace 命名空间。文档说明如下:
FROM 《Nacos 文档 ------ Nacos 概念》
命名空间
用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。
如此,我们可以通过给每个环境创建一个 Nacos namespace。然后,在每个 application-${profile}.yaml
配置文件中,配置对应的 Nacos namespace。
下面,我们来搭建一个结合 Nacos 的多环境的示例。
首先,让我们进行 Nacos 命名空间和配置集的创建。
3.1 创建 Nacos 命名空间
① 打开 Nacos UI 界面的「命名空间」菜单,进入「命名空间」功能。如下图所示:
② 点击列表右上角的「新建命名空间」按钮,弹出「新建命名空间」窗口,创建一个 dev
命名空间。输入如下内容,并点击「确定」按钮,完成创建。如下图所示:
③ 重复该操作,继续创建一个 prod
命名空间。最终 dev
和 prod
信息如下图:
3.2 创建 Nacos 配置集
① 打开 Nacos UI 界面的「配置列表」菜单,进入「配置管理」功能。如下图所示:
我们会发现,红圈部分多了 dev
和 prod
两个命名空间。
② 点击 dev
命名空间,然后点击列表右上角的➕号,进入「新建配置」界面,创建一个 Nacos 配置集。输入如下内容,并点击「发布」按钮,完成创建。如下图所示:
③ 点击 prod
命名空间,然后点击列表右上角的➕号,进入「新建配置」界面,创建一个 Nacos 配置集。输入如下内容,并点击「发布」按钮,完成创建。如下图所示:
如此,我们在 Nacos 中有 dev
、prod
命名空间。而这两命名空间下,都有一个 example
配置集。而这两配置集都有 server.port
配置项,用于启动不同端口的服务器。😈 为什么选择 server.port
配置呢?因为 Spring Boot 项目启动后,从日志中就可以看到生效的服务器端口,嘿嘿~
然后,让我们进行 Spring Boot 示例的搭建。
3.3 引入依赖
在 pom.xml
文件中,引入相关依赖。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lab-44-nacos-config-demo-profiles</artifactId>
<dependencies>
<!-- 实现对 SpringMVC 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 实现对 Nacos 作为配置中心的自动化配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.4</version>
</dependency>
</dependencies>
</project>
- 引入
spring-boot-starter-web
原来的原因是,我们会使用server.port
配置项,配置 Tomcat 的端口。
3.4 配置文件
在 resources
目录下,创建 2 个配置文件,对应不同的环境。如下:
application-dev.yaml
,开发环境。
nacos:
# Nacos 配置中心的配置项,对应 NacosConfigProperties 配置类
config:
server-addr: 127.0.0.1:18848 # Nacos 服务器地址
bootstrap:
enable: true # 是否开启 Nacos 配置预加载功能。默认为 false。
log-enable: true # 是否开启 Nacos 支持日志级别的加载时机。默认为 false。
data-id: example # 使用的 Nacos 配置集的 dataId。
type: YAML # 使用的 Nacos 配置集的配置格式。默认为 PROPERTIES。
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP。
namespace: 14226a0d-799f-424d-8905-162f6a8bf409 # 使用的 Nacos 的命名空间,默认为 null。
- 和「2.2 配置文件」不同的点,是修改了
nacos.config.namespace
配置项,设置为dev
命名空间的编号。
- 和「2.2 配置文件」不同的点,是修改了
application-prod.yaml
,生产环境。
nacos:
# Nacos 配置中心的配置项,对应 NacosConfigProperties 配置类
config:
server-addr: 127.0.0.1:18848 # Nacos 服务器地址
bootstrap:
enable: true # 是否开启 Nacos 配置预加载功能。默认为 false。
log-enable: true # 是否开启 Nacos 支持日志级别的加载时机。默认为 false。
data-id: example # 使用的 Nacos 配置集的 dataId。
type: YAML # 使用的 Nacos 配置集的配置格式。默认为 PROPERTIES。
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP。
namespace: f1686f3b-a984-4cdf-8298-7caee3455d14 # 使用的 Nacos 的命名空间,默认为 null。
另外,我们会创建 application.yaml
配置文件,放不同环境的相同配置 。例如说,spring.application.name
配置项,肯定是相同的啦。配置如下:
spring:
application:
name: demo-application
3.5 ProfilesApplication
创建 ProfilesApplication.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication
public class ProfilesApplication {
public static void main(String[] args) {
SpringApplication.run(ProfilesApplication.class, args);
}
}
3.6 简单测试
下面,我们使用命令行参数进行 --spring.profiles.active
配置项,实现不同环境,读取不同配置文件。
① 开发环境 示例:直接在 IDEA 中,增加 --spring.profiles.active=dev
到 Program arguments 中。如下图所示:
启动 Spring Boot 应用,输出日志如下:
# 省略其它日志...
2020-01-22 19:22:26.038 INFO 13059 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8081 (http)
- Tomcat 启动在 8081 端口,符合读取
dev
命名空间的example
配置集。
② 生产环境 示例:直接在 IDEA 中,增加 --spring.profiles.active=prod
到 Program arguments 中。如下图所示:
启动 Spring Boot 应用,输出日志如下:
# 省略其它日志...
2020-01-22 19:26:33.527 INFO 13162 --- [ main] o.s.b.w.embedded.tomcat.TomcatWebServer : Tomcat initialized with port(s): 8084 (http)
- Tomcat 启动在 8084 端口,符合读取
prod
命名空间的example
配置集。
另外,关于 Spring Boot 应用的多环境部署,胖友也可以看看《芋道 Spring Boot 持续交付 Jenkins 入门》文章。
4. 自动刷新配置
示例代码对应仓库:lab-44-nacos-config-demo-auto-refresh。
在上面的示例中,我们已经实现从 Nacos 读取配置。那么,在应用已经启动的情况下,如果我们将读取的 Nacos 的配置进行修改时,应用是否会自动刷新本地的配置呢?
如果是我们上面的示例,答案是不会。不过呢,Nacos 提供了上述功能,也就是自动刷新配置。下面,我们来搭建一个自动刷新配置的示例。
4.1 引入依赖
在 pom.xml
文件中,引入相关依赖。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lab-44-nacos-config-demo-auto-refresh</artifactId>
<dependencies>
<!-- 实现对 SpringMVC 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 实现对 Nacos 作为配置中心的自动化配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.4</version>
</dependency>
</dependencies>
</project>
- 引入
spring-boot-starter-web
依赖的原因,稍后我们会编写 API 接口,查看来自 Nacos 配置的最新值。
4.2 创建 Nacos 配置集
在 Nacos 中,创建一个用于测试自动刷新配置的配置集 example-auto-refresh
,具体内容如下图:
4.3 配置文件
在 application.yml
中,添加 Nacos 配置,如下:
nacos:
# Nacos 配置中心的配置项,对应 NacosConfigProperties 配置类
config:
server-addr: 127.0.0.1:18848 # Nacos 服务器地址
bootstrap:
enable: true # 是否开启 Nacos 配置预加载功能。默认为 false。
log-enable: true # 是否开启 Nacos 支持日志级别的加载时机。默认为 false。
data-id: example-auto-refresh # 使用的 Nacos 配置集的 dataId。
type: YAML # 使用的 Nacos 配置集的配置格式。默认为 PROPERTIES。
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP。
namespace: # 使用的 Nacos 的命名空间,默认为 null。
auto-refresh: true # 是否自动刷新,默认为 false。
- 和「2.2 配置文件」的差异点,是设置
nacos.config.auto-refresh
配置项为true
,开启 Nacos 自动刷新配置的功能。
4.4 TestProperties
在 cn.iocoder.springboot.lab44.nacosdemo.properties
包下,创建 TestProperties 配置类,读取 test
配置项。代码如下:
@Component
@NacosConfigurationProperties(prefix = "", dataId = "${nacos.config.data-id}", type = ConfigType.YAML, autoRefreshed = true)
public class TestProperties {
/**
* 测试属性
*/
private String test;
// ... 省略 set/get 方法
}
- 不同于「2.4 OrderProperties」,因为我们要使用自动刷新配置的功能,必须使用
@NacosConfigurationProperties
注解。
这里有一点要注意,nacos.config.auto-refresh
配置项开启的是全局 的,必须为 true
时,才能使用自动刷新配置的功能。同时,每个 @NacosConfigurationProperties
或 @NacosValue
注解,也需要设置 autoRefreshed
属性为 true
时,对应的配置项才会自动刷新。
4.5 DemoController
在 cn.iocoder.springboot.lab44.nacosdemo.controller
包下,创建 DemoController 类,提供返回配置的 API 接口。代码如下:
@RestController
@RequestMapping("/demo")
public class DemoController {
// @Value("${test}")
@NacosValue(value = "${test}", autoRefreshed = true)
private String test;
@GetMapping("/test")
public String test() {
return test;
}
@Autowired
private TestProperties testProperties;
@GetMapping("/test_properties")
public TestProperties testProperties() {
return testProperties;
}
}
/demo/test
接口,测试@NacosValue
注解。注意,这里为了实现自动刷新配置的功能,我们也无法使用@Value
注解,而是使用@NacosValue
替代。同时,设置其autoRefreshed
属性为true
。/demo/test_properties
接口,测试@NacosConfigurationProperties
注解的 TestProperties 配置类。
4.6 Application
创建 Application.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
4.7 简单测试
启动 Spring Boot 应用,开始我们本轮的测试。
① 分别请求 /demo/test
、/demo/test_properties
接口,响应结果如下:
# /demo/test 接口
芋艿
# /demo/test_properties 接口
{
"test": "芋艿"
}
② 修改 Nacos 配置集 example-auto-refresh
,将 test
配置项设置为 好帅
。如下图所示:
并且,我们可以看到控制台会输出大一堆 Nacos 的日志,如下图所示:
③ 分别请求 /demo/test
、/demo/test_properties
接口,响应结果如下:
# /demo/test 接口
好帅
# /demo/test_properties 接口
{
"test": "好帅"
}
- 自动刷新配置成功。
4.8 Nacos 配置监听器
通过 @NacosValue
和 @NacosConfigurationProperties
注解,已经能够满足我们绝大多数场景下的自动刷新配置的功能。但是,在一些场景下,我们仍然需要自定义 Nacos 配置监听器,实现对 Nacos 配置的监听,执行自定义的逻辑。
例如说,当数据库连接的配置发生变更时,我们需要通过监听该配置的变更,重新初始化应用中的数据库连接,从而访问到新的数据库地址。
又例如说,当日志级别发生变更时,我们需要通过监听该配置的变更,设置应用中的 Logger 的日志级别,从而后续的日志打印可以根据新的日志级别。
可能这么说,胖友会觉得有点抽象,我们来搭建一个日志级别的示例。
在 cn.iocoder.springboot.lab44.nacosdemo.listener
包下,创建 LoggingSystemConfigListener 类,监听 logging.level
配置项的变更,修改 Logger 的日志级别。代码如下:
@Component
public class LoggingSystemConfigListener {
/**
* 日志配置项的前缀
*/
private static final String LOGGER_TAG = "logging.level.";
@Resource
private LoggingSystem loggingSystem;
@NacosConfigListener(dataId = "${nacos.config.data-id}", type = ConfigType.YAML, timeout = 5000)
public void onChange(String newLog) throws Exception {
// <X> 使用 DefaultYamlConfigParse 工具类,解析配置
Properties properties = new DefaultYamlConfigParse().parse(newLog);
// <Y> 遍历配置集的每个配置项,判断是否是 logging.level 配置项
for (Object t : properties.keySet()) {
String key = String.valueOf(t);
// 如果是 logging.level 配置项,则设置其对应的日志级别
if (key.startsWith(LOGGER_TAG)) {
// 获得日志级别
String strLevel = properties.getProperty(key, "info");
LogLevel level = LogLevel.valueOf(strLevel.toUpperCase());
// 设置日志级别到 LoggingSystem 中
loggingSystem.setLogLevel(key.replace(LOGGER_TAG, ""), level);
}
}
}
}
loggingSystem
属性,是 Spring Boot Logger 日志系统,通过 LoggingSystem 可以进行日志级别的修改。- 在
#onChange(String newLog)
方法上,我们添加了@NacosConfigListener
注解,声明该方法处理指定配置集的配置变化。 <X>
处,使用 Nacos 提供的 DefaultYamlConfigParse 解析 YAML 格式的配置。示例如下图所示:- Nacos 还提供了 DefaultPropertiesConfigParse 解析 PROPERTIES 格式,DefaultXmlConfigParse 解析 XML 格式,DefaultJsonConfigParse 解析 JSON 格式。
<Y>
处,遍历配置集的每个配置项,判断如果是logging.level
配置项,则设置到 LoggingSystem 中,从而修改日志级别。详细的整个过程,胖友看看艿艿的详细的注释,嘿嘿~
4.9 再次测试
① 在 DemoController 类中,增加如下 API 接口。代码如下:
private Logger logger = LoggerFactory.getLogger(getClass());
@GetMapping("/logger")
public void logger() {
logger.debug("[logger][测试一下]");
}
- 如果 DemoController 对应的 Logger 日志级别是 DEBUG 以上,则无法打印出日志。
② 在 Nacos 中,修改测试自动刷新配置的配置集 example-auto-refresh
,具体内容如下图:
其中,配置内容如下,方便胖友复制:
test: 好帅
logging:
level:
cn:
iocoder:
springboot:
lab44:
nacosdemo:
controller:
DemoController: INFO
③ 启动 Spring Boot 应用,开始我们本轮的测试。
④ 请求 /demo/logger
接口,控制台并未打印日志,因为当前日志级别是 INFO。
⑤ 在 Nacos 中,修改测试自动刷新配置的配置集 example-auto-refresh
,具体内容如下图:
⑥ 请求 /demo/logger
接口,控制台打印日志,因为当前日志级别是 DEBUG。日志内容如下:
2020-01-23 14:40:41.484 DEBUG 23501 --- [nio-8080-exec-5] c.i.s.l.n.controller.DemoController : [logger][测试一下]
- 符合预期。
🐶 感兴趣的胖友,也可以在 LoggingSystemConfigListener 的监听方法增加断点,嘿嘿~
5. 配置加密
示例代码对应仓库:lab-44-nacos-config-demo-jasypt。
考虑到安全性,我们可能最好将配置文件中的敏感信息进行加密。例如说,MySQL 的用户名密码、第三方平台的 Token 令牌等等。不过,Nacos 暂时未内置配置加密的功能。官方文档说明如下:
FROM https://nacos.io/zh-cn/docs/faq.html
Nacos如何对配置进行加密
Nacos 计划在 1.X 版本提供加密的能力,目前还不支持加密,只能靠 sdk 做好了加密再存到 nacos 中。
因此,我们暂时只能在客户端进行配置的加解密。这里,我们继续采用在《芋道 Spring Boot 配置文件入门》的「8. 配置加密」小节中使用的 Jasypt。
下面,我们来使用 Nacos + Jasypt 搭建一个配置加密的示例。
5.1 引入依赖
在 pom.xml
文件中,引入相关依赖。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lab-44-nacos-config-demo-jasypt</artifactId>
<dependencies>
<!-- 实现对 SpringMVC 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 实现对 Nacos 作为配置中心的自动化配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.4</version>
</dependency>
<!-- 实现对 Jasypt 实现自动化配置 -->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.2</version>
<!-- <scope>test</scope>-->
</dependency>
<!-- 方便等会写单元测试 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>
- 引入
jasypt-spring-boot-starter
依赖,实现对 Jasypt 的自动化配置。
5.2 创建 Nacos 配置集
在 Nacos 中,创建一个用于测试配置加密的配置集 example-jasypt
,具体内容如下图:
这里为了测试简便,我们直接添加加密秘钥 jasypt.encryptor.password
配置项在该 Nacos 配置集中。如果为了安全性更高,实际建议把加密秘钥和配置隔离。不然,如果配置泄露,岂不是可以拿着加密秘钥,直接进行解密。
5.3 配置文件
在 application.yml
中,添加 Nacos 配置,如下:
nacos:
# Nacos 配置中心的配置项,对应 NacosConfigProperties 配置类
config:
server-addr: 127.0.0.1:18848 # Nacos 服务器地址
bootstrap:
enable: true # 是否开启 Nacos 配置预加载功能。默认为 false。
log-enable: true # 是否开启 Nacos 支持日志级别的加载时机。默认为 false。
data-id: example-jasypt # 使用的 Nacos 配置集的 dataId。
type: YAML # 使用的 Nacos 配置集的配置格式。默认为 PROPERTIES。
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP。
namespace: # 使用的 Nacos 的命名空间,默认为 null。
auto-refresh: true # 是否自动刷新,默认为 false。
- 和「4.3 配置文件」一样,就是换了一个配置集为
example-jasypt
。
5.4 Application
创建 Application.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
5.5 简单测试
下面,我们进行下简单测试。
- 首先,我们会使用 Jasypt 将
demo-application
进行加密,获得加密结果。 - 然后,将加密结果,赋值到 Nacos 配置集
example-jasypt
的spring.application.name
配置项。 - 最后,我们会使用 Jasypt 将
spring.application.name
配置项解密。
创建 JasyptTest 测试类,编写测试代码如下:
@RunWith(SpringRunner.class)
@SpringBootTest
public class JasyptTest {
@Autowired
private StringEncryptor encryptor;
@Test
public void encode() {
String applicationName = "demo-application";
System.out.println(encryptor.encrypt(applicationName));
}
@Value("${spring.application.name}")
// @NacosValue("${spring.application.name}")
private String applicationName;
@Test
public void print() {
System.out.println(applicationName);
}
}
- 首先,执行
#encode()
方法,手动 使用 Jasypt 将demo-application
进行加密,获得加密结果。加密结果如下:
nFVlMl4ZJ4vJLJ68X4x+a3CIerdaG0488LpZHKyoGxPoJkgemJT/nw==
然后,将加密结果,赋值到 Nacos 配置集
example-jasypt
的spring.application.name
配置项。如下图所示:最后,执行
#print()
方法,自动 使用 Jasypt 将spring.application.name
配置项解密。解密结果如下:
demo-application
- 成功正确解密,符合预期。
5.6 补充说明
目前测试下来,在将 Jasypt 集成进来时,Nacos 的「4. 自动配置刷新」功能,竟然失效了。
- 具体的验证,胖友可以将
jasypt-spring-boot-starter
依赖设置成<scope>test</scope>
,并是使用 DemoController 进行测试。 - 具体的原因,艿艿暂时没去调试与研究,有了解的胖友,麻烦告知下哟。
如果说,胖友暂时不需要自动配置刷新功能的话,可以考虑选择使用 Jasypt 集成。如果需要的话,那么就等待官方支持吧,暂时不要考虑使用 Jasypt 咧。
6. 监控端点
示例代码对应仓库:lab-44-nacos-config-demo-actuator。 在《芋道 Spring Boot 监控端点 Actuator 入门》中,我们学习了 Spring Boot Actuator 内置的监控端点。而 Nacos 有个 nacos-config-spring-boot-actuator 子项目,提供了 Nacos 作为 Spring Boot 配置中心时的监控端点。
下面,我们从「4. 自动刷新配置」的 lab-44-nacos-config-demo-auto-refresh 示例项目,复制出 lab-44-nacos-config-demo-actuator 作为本小节的示例。当然,我们还需要将 Actuator 集成到其中。
6.1 引入依赖
修改 pom.xml
文件中,额外引入 Actuator 相关依赖。
<!-- 实现对 Actuator 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
<!-- 实现对 Nacos 作为配置中心的 Actuator 的自动化配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-actuator</artifactId>
<version>0.2.4</version>
</dependency>
6.2 配置文件
修改 application.yaml
配置文件,额外引入 Actuator 相关配置。
management:
endpoint:
# Health 端点配置项,对应 HealthProperties 配置类
health:
show-details: ALWAYS # 何时显示完整的健康信息。默认为 NEVER 都不展示。可选 WHEN_AUTHORIZED 当经过授权的用户;可选 ALWAYS 总是展示。
endpoints:
# Actuator HTTP 配置项,对应 WebEndpointProperties 配置类
web:
exposure:
include: '*' # 需要开放的端点。默认值只打开 health 和 info 两个端点。通过设置 * ,可以开放所有端点。
- 每个配置项的用途,胖友看下艿艿添加的详细注释。
配置完成后,启动 Spring Boot 应用,我们可以开始测试 Nacos 提供的监控端点了。
6.3 health 端点
health
端点,是 Spring Boot Actuator 内置的健康状态端点。而 Nacos 自定义了 HealthIndicator 实现类 NacosConfigHealthIndicator,获取应用连接 Nacos 的健康状态。
请求 actuator/health
地址,获取健康状态结果如下图:
6.4 nacos-config 端点
nacos-config
端点,是 Nacos 自定义端点 NacosConfigEndpoint,获得 Nacos 在 Spring Boot 的配置信息。
请求 actuator/nacos-config
地址,获取健康状态结果如下图:
7. 配置加载顺序
示例代码对应仓库:lab-44-nacos-config-demo-multi。
在《芋道 Spring Boot 配置文件入门》的「9. 配置加载顺序」小节,我们了解了 Spring Boot 自带的配置加载顺序。本小节,我们来看看来自 Nacos 的配置,在其中的顺序。同时,我们将配置多个 Nacos 配置集,看看它们互相之间的加载顺序。
下面,我们来搭建一个用于测试配置加载顺序的示例。
7.1 引入依赖
在 pom.xml
文件中,引入相关依赖。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.2.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>lab-44-nacos-config-demo-multi</artifactId>
<dependencies>
<!-- 实现对 SpringMVC 的自动化配置 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 实现对 Nacos 作为配置中心的自动化配置 -->
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.4</version>
</dependency>
</dependencies>
</project>
- 和「2.1 引入依赖」是一致的。
7.2 配置文件
在 application.yml
中,添加 Nacos 配置,如下:
nacos:
# Nacos 配置中心的配置项,对应 NacosConfigProperties 配置类
config:
server-addr: 127.0.0.1:18848 # Nacos 服务器地址
bootstrap:
enable: true # 是否开启 Nacos 配置预加载功能。默认为 false。
log-enable: true # 是否开启 Nacos 支持日志级别的加载时机。默认为 false。
data-id: example-multi-01 # 使用的 Nacos 配置集的 dataId。
# data-ids: example-multi-02
type: YAML # 使用的 Nacos 配置集的配置格式。默认为 PROPERTIES。
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP。
namespace: # 使用的 Nacos 的命名空间,默认为 null。
auto-refresh: true # 是否自动刷新,默认为 false。
ext-config:
- server-addr: 127.0.0.1:18848 # Nacos 服务器地址
# data-id: example-multi-11 # 使用的 Nacos 配置集的 dataId。
data-ids: example-multi-11, example-multi-12
type: YAML # 使用的 Nacos 配置集的配置格式。默认为 PROPERTIES。
group: DEFAULT_GROUP # 使用的 Nacos 配置分组,默认为 DEFAULT_GROUP。
namespace: # 使用的 Nacos 的命名空间,默认为 null。
auto-refresh: true # 是否自动刷新,默认为 false。
# - # 这里,可以继续添加。
- 在
nacos.config
配置项下,可以通过data-id
和data-ids
来设置使用的 Nacos 配置集。不过要注意,这两者只能二选一。 - 在
nacos.config.ext-config
配置项下,它是 Config 数组,可以配置多个配置集。实际上,Config 的属性和nacos.config
是基本类似的,从艿艿这里给出来的示例,是不是已经可以发现啦。不过要注意,nacos.config
配置项下的优先级高于nacos.config.ext-config
。
这里,Nacos 配置集 example-multi-01
、example-multi-11
、example-multi-12
需要创建下,具体的配置内容随意哈。
7.3 Application
创建 Application.java
类,配置 @SpringBootApplication
注解即可。代码如下:
@SpringBootApplication
// @NacosPropertySource(dataId = "example", type = ConfigType.YAML)
public class Application {
public static void main(String[] args) {
// 启动 Spring Boot 应用
ConfigurableApplicationContext context = SpringApplication.run(Application.class, args);
// 查看 Environment
Environment environment = context.getEnvironment();
System.out.println(environment);
}
}
在代码中,我们去获取了 Spring Environment 对象,因为我们要从其中获取到 PropertySource 配置来源。DEBUG 运行 Application,并记得在 System.out.println(environment);
代码块打一个断点,可以看到如下图的调试信息:
- 每一个 Nacos 配置集,对应一个 PropertySource 对象,并且
nacos.config
配置项下的优先级高于nacos.config.ext-config
。 - 所有 Nacos 配置集的 PropertySource 对象,排在
application.yaml
配置文件的 PropertySource 对象后面,也就是优先级最低。
来源:https://blog.csdn.net/weixin_42073629/article/details/106304395