使用 Nacos 的配置功能和自动更新
Nacos 不但可以作为注册中心,同时也可以作为配置中心,方便我们对 SpringCloud 中的各个 SpringBoot 微服务的配置进行统一的管理维护。尤其是当微服务数量较多,并且在不同的服务器上进行部署时,使用配置中心进行统一管理维护的优势就更加明显。
本篇博客仍然使用之前搭建的 Nacos 集群,并在上篇博客 Demo 的基础上进行简单的改造,实现微服务从 Nacos 中读取配置,并且在不重启微服务的前提下,实现微服务代码读取的配置内容,跟随 Nacos 配置的修改而自动更新。本篇博客只介绍关键核心内容,详情请查看源代码,在博客最后会提供源代码下载。
一、微服务的配置文件
首先看一下 Demo 的 SpringCloud 工程结构,如下图所示:
工程中有两个微服务 consumer_app 和 provider_app ,使用的服务名称分别为 consumer 和 provider 。
需要注意的是:微服务想要读取 Nacos 中的配置文件,配置文件的名称需要以微服务的名称来命名。因此我们需要在 Nacos 中添加两个配置文件:consumer.yaml 和 provider.yaml 。
当然并非所有的配置内容,都放到 nacos 中进行管理,这个可以根据项目的实际情况而定。以 consumer_app 为例,我们将其配置分别存放在 3 个配置文件中:本地的 application.yml 和 bootstrap.yml ,以及 Nacos 中的 consumer.yaml 。下面先看一下这 3 个配置文件的内容:
本地 bootstrap.yml 的内容如下:(spring 引入了 bootstrap.yaml 文件,会在 application.yml 之前被加载)
#微服务启动后,会优先加载 bootstrap.yml 文件,这里只配置了服务名称,以及nacos连接信息 #本地的 application.yml 也是会加载的,比如服务启动端口就配置在 application.yml 中。 spring: application: # 微服务的名称,这个很重要,因为需要到 nacos 中获取【微服务名称.yaml】的配置文件 name: consumer cloud: nacos: # 配置 Nacos 的 ip 和 端口 server-addr: 192.168.216.129:80 # 配置登录的 账号 和 密码 username: nacos password: nacos config: file-extension: yaml
本地 application.yml 的内容如下:
# 本地配置文件,在微服务启动时,也会被加载 server: port: 8888 #针对具体的服务,配置使用 nacos 的负载均衡策略(随机策略) #当前项目中接口提供者的服务名称是 provider #如果去掉以下的配置,则默认使用 ribbon 的轮训策略 provider: ribbon: NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule logging: level: com.jobs: debug
Nacos 中的 consumer.yaml 的配置内容如下:
二、读取 Nacos 中的配置以及自动更新
1 父工程和子工程需要引入的依赖
父工程的 pom 文件中需要引入 SpringCloud Alibaba 的依赖:
<!--引入 springCloud alibaba 依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>2.2.9.RELEASE</version> <type>pom</type> <scope>import</scope> </dependency>
需要注意版本之间的兼容性,否则可能会出问题。本篇博客中,使用的版本如下:
- SpringBoot 的版本为 2.3.12.RELEASE
- SpringCloud 版本为 Hoxton.SR10
- SpringCloud Alibaba 的版本为 2.2.9.RELEASE
这里以 consumer_app 子工程为例,需要的依赖如下:
<!--nacos配置管理依赖--> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency>
2 使用 @Value 方式读取配置和自动更新
我们以读取 Nacos 中的 consumer.yaml 的 myvalue.dateformat 中的值为例,更改一下 ConsumerController 代码。添加一个新的接口,并在 Controller 上添加 @RefreshScope 注解,核心代码如下所示:
/* 如果使用 $Value 来获取 nacos 中配置文件的配置值, 当 nacos 中配置值修改后,要想让程序中获取的值也立刻更新, 就需要在类上添加 @RefreshScope 注解 */ @RefreshScope @RequestMapping("/consumer") @RestController public class ConsumerController { @Value("${myvalue.dateformat}") private String dateformat; @GetMapping("/now") public String getDateNow() { return LocalDateTime.now().format(DateTimeFormatter.ofPattern(dateformat)); } }
3 使用 @ConfigurationProperties 的配置类和自动更新
我们以读取 Nacos 中的 consumer.yaml 的 myconfig 下的 name 和 age 的值为例,首先需要添加一个与 Nacos 中配置内容相对应的映射类,具体代码如下所示:
package com.jobs.configpojo; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Data @Component @ConfigurationProperties(prefix = "myconfig") public class MyConfig { private String name; private Integer age; }
新创建一个 ConfigTestController 和接口,读取配置的代码如下所示:
package com.jobs.controller; import com.jobs.configpojo.MyConfig; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; /* 如果使用 @ConfigurationProperties 为注解的配置类映射 nacos 配置文件的配置信息, 那么当 nacos 中的配置值修改后,则程序中就能够自动获取到更新,这种方式更加方便 */ @RequestMapping("/config") @RestController public class ConfigTestController { @Autowired private MyConfig myConfig; @GetMapping("/getdata") public MyConfig getMyConfig() { return myConfig; } }
三、相同配置内容的优先级
在 Nacos 中除了【微服务名称.yaml】配置文件外,也可以添加【微服务名称-profile名称.yaml】配置文件,以 provider_app 为例,我们可以在 Nacos 中添加 2 个配置文件:provider.yaml 和 provider-dev.yaml。
我们可以把一些公用的配置放在【微服务名称.yaml】配置文件中,对于不同环境的中有差异的配置,可以放在【微服务名称-profile名称.yaml】配置文件中,如常用的环境为:开发环境 dev 、测试环境 test 、生成环境 pro 等等,这个名称可以自己随便取。
首先对于 bootstrap.yml 配置文件,由于其加载的时间最早,绝大多数情况下,我们只会将【微服务名称】、【profile 名称】、【Nacos 连接信息】配置在里面,不会配置其它额外的信息,对于 provider_app 微服务来说,其 bootstrap.yml 文件内容如下:
#微服务启动后,会优先加载 bootstrap.yml 文件,这里只配置了服务名称,以及nacos连接信息 #本地的 application.yml 也是会加载的,比如服务启动端口就配置在 application.yml 中。 spring: application: # 微服务的名称,这个很重要,因为需要到 nacos 中获取【微服务名称.yaml】的配置文件 name: provider profiles: #开发环境,比如可以使用 test 表示测试环境,pro 表示生产环境 active: dev cloud: nacos: # 配置 Nacos 的 ip 和 端口 server-addr: 192.168.216.129:80 # 配置登录的 账号 和 密码 username: nacos password: nacos config: file-extension: yaml
由于在 bootstrap.yml 文件中配置了 spring.profiles.active 为 dev ,因此 provider_app 微服务启动时,会加载这几个配置文件:本地的 application.yml 、Nacos 中的 provider.yaml 和 provider-dev.yaml ,下面列出这 3 个文件的相同名称的配置:
本地 application.yml 的配置内容:
server: port: 9091 logging: level: com.jobs: debug mytest: name: 本地配置值 depart: 本地部门
Nacos 中添加的 provider.yaml 的配置内容:
Nacos 中添加的 provider-dev.yaml 的配置内容:
可以看到 3 个配置文件,都有 mytest 下的 name 和 depart 的配置,具体会使用哪个配置内容呢?
在本篇博客的代码中,使用了 @ConfigurationProperties 的配置类的方式读取以上配置,并提供的接口进行验证。首先新增一个与 Nacos 配置映射的配置类,具体细节如下所示:
package com.jobs.configpojo; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.stereotype.Component; @Data @Component @ConfigurationProperties(prefix = "mytest") public class MyTest { private String name; private String depart; }
然后更改了一下对外提供的接口,代码如下:
package com.jobs.controller; import com.jobs.configpojo.MyTest; import com.jobs.pojo.Employee; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.io.UnsupportedEncodingException; import java.util.Random; @Slf4j @RequestMapping("/provider") @RestController public class ProviderController { @Autowired private MyTest myTest; @GetMapping("/{id}") public Employee getEmployeeById(@PathVariable("id") Integer id) { Employee employee = new Employee(); employee.setId(id); //使用配置文件中的配置值 //配置文件优先级:provider-dev.yaml > provider.yaml > application.yml //你可以分别注释 nacos 中 provider-dev.yaml 和 provider.yaml 中的配置,进行验证结果 employee.setName(myTest.getName()); employee.setDepart(myTest.getDepart()); log.info("返回员工的 id 为:" + id); return employee; } }
你可以分别 Nacos 中的 provider-dev.yaml 和 provider.yaml 中的配置注释和启用,进行验证,最终的结果为:
【微服务名称-profile名称.yaml】 > 【微服务名称.yaml】 > 【本地 application.yml】
本篇博客的源代码下载地址为:https://files.cnblogs.com/files/blogs/699532/nacos_config.zip
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具