配置中心:Nacos Config
第二个灵魂拷问:100 个服务改个日志级别,要改 100 个文件再重启 100 次?单体里配置写在 application.yml 里,简单粗暴。微服务时代,每个服务一份配置,数据库密码改一次要翻 50 个仓库。配置中心就是把所有配置集中到 Nacos 上,改一处、秒推所有服务。
论Nacos Config 的三个核心概念
Namespace:还是那个命名空间,配置也按 dev/test/prod 隔离。
Group:同一环境里的业务分组,不分组也行,默认 DEFAULT_GROUP。
Data ID:配置文件的唯一名字。Nacos 找一份配置靠的就是 Data ID。默认规则是 ${spring.application.name}-${spring.profiles.active}.${file-extension},比如 user-service-dev.yaml。
动态刷新:配置改了,加了 @RefreshScope 注解的 Bean 会自动拿到新值,不用重启服务。这是配置中心最爽的地方。
接入 Nacos Config:bootstrap 配置
Spring Boot 3.x 之后,bootstrap.yml 默认不加载了,需要额外引入 spring-cloud-starter-bootstrap,或者直接在 application.yml 里配。新项目推荐后者。下面给一个能跑的写法。
pom.xml 里加配置中心依赖
application.yml:告诉 Spring 启动时去 Nacos 拉配置
业务代码里用 @Value 注入配置,并加 @RefreshScope 实现热刷新
很多人奇怪"我 Nacos 上明明配了,怎么不生效?"——多半是本地 application.yml 把 Nacos 的值覆盖了。Spring Boot 配置优先级里,命令行参数 > 环境变量 > Nacos 远程配置 > 本地 application.yml(具体以官方文档为准)。也就是说,本地配置优先级更低,通常不会覆盖 Nacos;但如果你用了 --spring.config.import 或 profile 写死,就可能出问题。排错时先看启动日志里 Nacos Config 是不是真的拉到了配置。
配置优先级一张表
Spring Boot 配置有个优先级问题——同一个 key,从多个地方读到时以谁为准。数字越小优先级越高(覆盖别人),具体以 Spring Boot 官方文档为准:
| 优先级 | 来源 |
|---|---|
| 1(最高) | 命令行参数(--user.welcome=xxx) |
| 2 | 操作系统环境变量、系统属性 |
| 3 | Nacos 远程配置(通过 spring.config.import 引入) |
| 4 | 本地 application.yml / application-{profile}.yml |
| 5(最低) | 代码里的默认值(@Value("${x:默认值}")) |
所以想让 Nacos 配置生效,别在本地 application.yml 里写同一个 key——本地会按上面优先级跟你抢。本地只放"连 Nacos 必须的"配置(server-addr、namespace),业务配置全放 Nacos。
灰度发布:让新版本配置先跑在几台机器上
改配置最怕一把全量推出去,结果配错了全站崩。Nacos 支持"灰度发布"——先把新配置推给指定的几台机器(按 IP 或元数据挑),观察没问题再全量。控制台里选"灰度"即可,代码不用改。学习阶段知道有这功能就行,生产环境是救命用的。
完整案例:两个微服务 + Nacos 注册发现 + 配置热刷新
光看概念没劲,跑一遍才懂。我们搭两个服务:order-service(订单)和 user-service(用户),都注册到 Nacos;user-service 读 Nacos 上的一句欢迎语,用 @RefreshScope 实现改配置不重启。
第一步:起 Nacos,控制台建配置
第二步:user-service 的 application.yml(连注册中心 + 拉远程配置)
第三步:user-service 控制器,@RefreshScope 实现热刷新
第四步:跑起来验证(不用重启!)
论注册发现 + 配置热刷新,到底干了啥
注册:user-service 启动时把自己的 IP:端口 报给 Nacos。
发现:order-service 要调 user-service,不写死 IP,按名字 user-service 问 Nacos 要地址。
热刷新:Nacos 配置一变,通过长连接推给所有监听的服务,带 @RefreshScope 的 Bean 自动重建、拿到新值。
① 忘了加 @RefreshScope——普通 Bean 注入一次就固定,必须加注解才会响应刷新。② 配置没真的拉到——看启动日志有没有 Located property source: [Nacos],没有就是 spring.config.import 或 Data ID 写错了。