文章目录
- [Spring Cloud 学习与实践(6):Nacos 配置中心](#Spring Cloud 学习与实践(6):Nacos 配置中心)
-
- [1. 本章目标](#1. 本章目标)
- [2. 注册中心与配置中心的区别](#2. 注册中心与配置中心的区别)
- [3. 为什么需要配置中心](#3. 为什么需要配置中心)
- [4. 本章版本说明](#4. 本章版本说明)
- [5. DataId、Group 与 Namespace](#5. DataId、Group 与 Namespace)
-
- [5.1 DataId](#5.1 DataId)
- [5.2 Group](#5.2 Group)
- [5.3 Namespace](#5.3 Namespace)
- [6. 本项目为什么同时使用 bootstrap.yml 和 application.yml](#6. 本项目为什么同时使用 bootstrap.yml 和 application.yml)
-
- [6.1 普通 Spring Boot 通常只需要 application.yml](#6.1 普通 Spring Boot 通常只需要 application.yml)
- [6.2 本项目使用的是传统 Spring Cloud bootstrap 模式](#6.2 本项目使用的是传统 Spring Cloud bootstrap 模式)
- [6.3 application.yml 继续保存普通本地配置](#6.3 application.yml 继续保存普通本地配置)
- [6.4 两个文件并不是必须同时存在](#6.4 两个文件并不是必须同时存在)
- [6.5 当前项目启动链路](#6.5 当前项目启动链路)
- [7. cloud-user 接入 Nacos Config](#7. cloud-user 接入 Nacos Config)
-
- [7.1 添加依赖](#7.1 添加依赖)
- [8. 创建 cloud-user/bootstrap.yml](#8. 创建 cloud-user/bootstrap.yml)
- [9. 在 Nacos 中创建 cloud-user-dev.yaml](#9. 在 Nacos 中创建 cloud-user-dev.yaml)
-
- [为什么 DataId 是 cloud-user-dev.yaml?](#为什么 DataId 是 cloud-user-dev.yaml?)
- [10. 创建 ConfigController](#10. 创建 ConfigController)
- [11. 启动时读取远程配置](#11. 启动时读取远程配置)
- [12. 故障演练:配置变更已被监听,但接口仍返回旧值](#12. 故障演练:配置变更已被监听,但接口仍返回旧值)
- [13. 为什么监听到变化后,@Value 仍然不刷新](#13. 为什么监听到变化后,@Value 仍然不刷新)
- [14. 添加 @RefreshScope](#14. 添加 @RefreshScope)
- [15. 验证动态刷新成功](#15. 验证动态刷新成功)
- [16. Nacos 配置读取完整链路](#16. Nacos 配置读取完整链路)
-
- [16.1 启动阶段链路](#16.1 启动阶段链路)
- [16.2 当前 cloud-user 的实际定位](#16.2 当前 cloud-user 的实际定位)
- [16.3 动态刷新链路](#16.3 动态刷新链路)
- [17. 长轮询还是长连接](#17. 长轮询还是长连接)
-
- [Nacos 1.x](#Nacos 1.x)
- [Nacos 2.x](#Nacos 2.x)
- [18. cloud-product 接入配置中心](#18. cloud-product 接入配置中心)
-
- [18.1 添加依赖](#18.1 添加依赖)
- [18.2 创建 bootstrap.yml](#18.2 创建 bootstrap.yml)
- [18.3 创建 Nacos 配置](#18.3 创建 Nacos 配置)
- [18.4 创建 ConfigController](#18.4 创建 ConfigController)
- [19. cloud-order 接入配置中心](#19. cloud-order 接入配置中心)
-
- [19.1 添加依赖](#19.1 添加依赖)
- [19.2 创建 bootstrap.yml](#19.2 创建 bootstrap.yml)
- [19.3 创建 Nacos 配置](#19.3 创建 Nacos 配置)
- [19.4 创建 ConfigController](#19.4 创建 ConfigController)
- [20. 创建 dev Namespace](#20. 创建 dev Namespace)
- [21. 在 dev Namespace 中创建三份配置](#21. 在 dev Namespace 中创建三份配置)
- [22. 三个服务切换到 dev Namespace](#22. 三个服务切换到 dev Namespace)
- [23. 为什么修改 Namespace 后必须重启](#23. 为什么修改 Namespace 后必须重启)
- [24. Namespace 环境隔离验证](#24. Namespace 环境隔离验证)
- [25. 为什么不把重复依赖全部放入 cloud-common](#25. 为什么不把重复依赖全部放入 cloud-common)
-
- [25.1 cloud-common 应保持职责单一](#25.1 cloud-common 应保持职责单一)
- [25.2 依赖具有传递性](#25.2 依赖具有传递性)
- [25.3 Starter 可能触发自动配置](#25.3 Starter 可能触发自动配置)
- [25.4 推荐做法](#25.4 推荐做法)
- [26. @Value 与 @ConfigurationProperties](#26. @Value 与 @ConfigurationProperties)
- [27. 本章常见问题](#27. 本章常见问题)
-
- [27.1 bootstrap.yml 是不是优先级最高?](#27.1 bootstrap.yml 是不是优先级最高?)
- [27.2 为什么普通 Bean 不会自动刷新 @Value?](#27.2 为什么普通 Bean 不会自动刷新 @Value?)
- [27.3 @RefreshScope 做了什么?](#27.3 @RefreshScope 做了什么?)
- [27.4 Namespace 为什么要填写 ID?](#27.4 Namespace 为什么要填写 ID?)
- [27.5 Group 当前为什么保持 DEFAULT_GROUP?](#27.5 Group 当前为什么保持 DEFAULT_GROUP?)
- [27.6 配置中心和注册中心是否必须使用同一个 Nacos Server?](#27.6 配置中心和注册中心是否必须使用同一个 Nacos Server?)
- [27.7 配置中心概念与链路](#27.7 配置中心概念与链路)
- [28. 本章结论](#28. 本章结论)
Spring Cloud 学习与实践(6):Nacos 配置中心
本章目标:在
cloud-user、cloud-product、cloud-order中接入 Nacos Config,理解远程配置从 Nacos Server 进入 Spring Environment 的完整链路;通过@Value与@RefreshScope故障演练,掌握动态刷新机制;最后使用 Namespace 完成开发环境隔离。
1. 本章目标
上一章已经完成 Nacos 注册中心接入:
text
Nacos Server 单机模式启动
cloud-user 注册到 Nacos
cloud-product 注册到 Nacos
cloud-order 注册到 Nacos
服务实例上下线观察
服务、实例、集群概念
临时实例与持久实例概念
多网卡注册 IP 问题说明
本章继续使用 Nacos,但关注另一个能力:
text
Nacos 配置中心
本章主要完成:
text
1. 理解注册中心与配置中心的区别
2. 为三个业务服务添加 Nacos Config 依赖
3. 使用 bootstrap.yml 配置远程配置加载信息
4. 在 Nacos 中创建 cloud-user-dev.yaml
5. 使用 @Value 读取 biz.version
6. 故意不添加 @RefreshScope,观察动态刷新不生效
7. 添加 @RefreshScope,验证无需重启即可刷新
8. 为 cloud-product 和 cloud-order 接入配置中心
9. 创建 dev Namespace
10. 将三个服务切换到 dev Namespace
11. 理解 DataId、Group、Namespace
12. 理解 Nacos 配置从发布到 Bean 刷新的完整链路
2. 注册中心与配置中心的区别
Nacos 同时提供:
text
注册中心
配置中心
但两者解决的问题不同。
| 能力 | 作用 |
|---|---|
| 注册中心 | 管理服务实例地址、端口和健康状态 |
| 配置中心 | 集中管理配置,并支持动态刷新 |
注册中心解决的问题
text
cloud-order 如何找到 cloud-product?
cloud-product 有几个实例?
某个实例是否健康?
配置中心解决的问题
text
多个服务的配置如何统一管理?
修改配置后是否必须重新打包?
是否必须重启服务?
不同环境如何隔离?
一句话总结:
text
注册中心解决"服务在哪里";
配置中心解决"服务用什么配置"。
3. 为什么需要配置中心
当前项目中,每个服务都有本地配置文件:
text
cloud-user/src/main/resources/application.yml
cloud-product/src/main/resources/application.yml
cloud-order/src/main/resources/application.yml
如果未来有:
text
30 个服务
每个服务部署 5 个实例
那么修改一个业务开关时,如果仍然逐个修改本地文件,就会面临:
text
配置分散
修改麻烦
容易遗漏
需要重新打包
需要重启服务
不同环境容易混乱
配置中心的目标是:
text
配置集中管理
↓
服务启动时读取远程配置
↓
配置修改后通知客户端
↓
部分配置无需重启即可生效
4. 本章版本说明
当前项目统一版本:
text
JDK:17
Spring Boot:2.7.18
Spring Cloud:2021.0.8
Spring Cloud Alibaba:2021.0.5.0
Nacos Server:2.2.0
本章继续使用传统方式:
text
bootstrap.yml
+
spring-cloud-starter-bootstrap
较新的 Spring Cloud 生态逐步推荐:
text
spring.config.import
但本课程为了保持版本一致,并便于理解启动早期配置加载过程,仍然使用 bootstrap.yml。
5. DataId、Group 与 Namespace
Nacos 中的一份配置,不是只靠文件名定位。
可以理解为:
text
Namespace
+
Group
+
DataId
5.1 DataId
DataId 可以理解为配置文件名。
例如:
text
cloud-user-dev.yaml
通常包含:
text
服务名
环境
扩展名
5.2 Group
Group 可以理解为配置分组。
默认值:
text
DEFAULT_GROUP
后续可以扩展:
text
COMMON_GROUP
ORDER_GROUP
PRODUCT_GROUP
5.3 Namespace
Namespace 用于环境隔离。
常见划分:
text
dev
test
prod
不同 Namespace 中可以存在相同:
text
Group
DataId
例如:
text
dev Namespace
└── DEFAULT_GROUP
└── cloud-user-dev.yaml
prod Namespace
└── DEFAULT_GROUP
└── cloud-user-dev.yaml
一句话总结:
text
DataId 表示配置文件,
Group 表示配置分组,
Namespace 表示环境隔离。
6. 本项目为什么同时使用 bootstrap.yml 和 application.yml
6.1 普通 Spring Boot 通常只需要 application.yml
在普通 Spring Boot 项目中,最常用的配置文件是:
text
application.yml
application-{profile}.yml
Spring Boot 会在启动时自动加载这些配置文件。
bootstrap.yml 不是普通 Spring Boot 默认等价支持的另一个主配置文件。
6.2 本项目使用的是传统 Spring Cloud bootstrap 模式
本项目为了接入 Nacos 配置中心,引入了:
xml
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
启用传统 bootstrap 模式后,Spring Cloud 会先创建 bootstrap 上下文,再创建主应用上下文。
因此,本项目将启动早期需要使用的配置放入:
text
bootstrap.yml
例如:
yaml
spring:
application:
name: cloud-user
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
namespace: dev-namespace-id
group: DEFAULT_GROUP
file-extension: yaml
这些配置用于告诉 Nacos Config 客户端:
text
连接哪个 Nacos Server
使用哪个 Namespace
使用哪个 Group
读取哪个 DataId
6.3 application.yml 继续保存普通本地配置
例如:
yaml
server:
port: 9200
spring:
datasource:
url: jdbc:mysql://localhost:3306/cloud_demo
username: root
password: xxx
这种拆分是为了让职责更清晰:
text
bootstrap.yml:
启动早期外部配置定位信息
application.yml:
普通本地应用配置
Nacos 远程配置:
需要集中管理、环境隔离或动态刷新的配置
这是一种工程约定,不是绝对限制。
6.4 两个文件并不是必须同时存在
不要理解成:
text
使用 Nacos Config
就必须同时存在 bootstrap.yml 和 application.yml
实际上:
text
application.yml 可以不存在,
只要主应用没有需要单独保存的本地配置。
较新的 Spring Cloud Alibaba 还可以使用:
text
application.yml
+
spring.config.import
直接导入 Nacos 配置,不再使用 bootstrap.yml。
因此,本项目当前使用的:
text
bootstrap.yml
+
application.yml
只是传统 bootstrap 接入模式下较清晰的一种组织方式。
6.5 当前项目启动链路
text
Spring Boot 启动
↓
Spring Cloud 创建 bootstrap 上下文
↓
读取 bootstrap.yml
↓
获得 Nacos Server、Namespace、Group、服务名等元信息
↓
Nacos Config 客户端拉取远程配置
↓
远程配置加入 Spring Environment
↓
创建主应用上下文
↓
application.yml 等本地配置参与属性解析
↓
业务 Bean 读取最终配置
一句话总结:
text
bootstrap.yml 不是 Nacos 强制要求,
而是当前项目采用传统 bootstrap 模式时,
用于保存启动早期配置的一种约定文件。
7. cloud-user 接入 Nacos Config
先用 cloud-user 完成最小闭环。
7.1 添加依赖
在 cloud-user/pom.xml 中加入:
xml
<!--
Nacos Config:
从 Nacos 配置中心读取远程配置,
并支持配置变更监听。
-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--
启用 bootstrap.yml 加载阶段。
-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
原有 Discovery 依赖继续保留:
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
8. 创建 cloud-user/bootstrap.yml
位置:
text
cloud-user
└── src/main/resources
└── bootstrap.yml
内容:
yaml
spring:
application:
# 服务名称。
# 既用于注册中心,也参与配置中心 DataId 推导。
name: cloud-user
profiles:
# 当前激活开发环境。
active: dev
cloud:
nacos:
config:
# Nacos 配置中心地址。
server-addr: 127.0.0.1:8848
# 配置文件扩展名。
file-extension: yaml
# 当前使用默认分组。
group: DEFAULT_GROUP
9. 在 Nacos 中创建 cloud-user-dev.yaml
进入 Nacos 控制台:
text
配置管理
↓
配置列表
↓
创建配置
填写:
| 配置项 | 值 |
|---|---|
| Data ID | cloud-user-dev.yaml |
| Group | DEFAULT_GROUP |
| 配置格式 | YAML |
内容:
yaml
biz:
version: v1
如图↓

为什么 DataId 是 cloud-user-dev.yaml?
因为:
yaml
spring:
application:
name: cloud-user
profiles:
active: dev
cloud:
nacos:
config:
file-extension: yaml
对应规则:
text
${spring.application.name}-${spring.profiles.active}.${file-extension}
代入后:
text
cloud-user-dev.yaml
10. 创建 ConfigController
创建:
text
cloud-user
└── src/main/java
└── com.example.cloud.user.controller
└── ConfigController.java
第一阶段代码:
java
package com.example.cloud.user.controller;
import com.example.cloud.common.result.Result;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Nacos 配置中心测试接口。
*
* 当前故意不添加 @RefreshScope。
*
* 目标:
* 1. 验证启动时能否读取远程配置
* 2. 修改配置后观察普通 Bean 是否会自动刷新
*/
@RestController
@RequestMapping("/config")
public class ConfigController {
/**
* 从 Spring Environment 中读取 biz.version。
*
* local-default 是默认值。
* 如果远程配置加载失败,接口会返回 local-default。
*/
@Value("${biz.version:local-default}")
private String bizVersion;
@GetMapping("/version")
public Result<String> version() {
return Result.success(bizVersion);
}
}
11. 启动时读取远程配置
启动:
text
CloudUserApplication
访问:
http
GET http://localhost:9200/config/version
返回:
json
{
"code": 0,
"message": "success",
"data": "v1"
}
说明:
text
cloud-user 启动时已经成功读取 Nacos 配置
如图↓

12. 故障演练:配置变更已被监听,但接口仍返回旧值
在 Nacos 中将:
yaml
biz:
version: v1
修改为:
yaml
biz:
version: v2
如图↓

发布后,日志出现:
text
Refresh keys changed: [biz.version]
如图 ↓

但是再次访问:
http
GET http://localhost:9200/config/version
仍然返回:
json
{
"code": 0,
"message": "success",
"data": "v1"
}
现象总结
text
Nacos 已经发布 v2
↓
客户端已经监听到 biz.version 变化
↓
接口仍然返回 v1
13. 为什么监听到变化后,@Value 仍然不刷新
当前 Controller 是普通 Spring Bean。
启动时:
text
ConfigController 创建
↓
@Value 注入 v1
后续 Nacos 修改配置:
text
Nacos 发布 v2
↓
客户端感知变化
↓
Spring Environment 更新
↓
普通 ConfigController 仍然是旧对象
↓
字段仍然保留 v1
核心结论:
text
Environment 更新
≠
普通 Bean 字段自动重新注入
14. 添加 @RefreshScope
修改 ConfigController:
java
package com.example.cloud.user.controller;
import com.example.cloud.common.result.Result;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* Nacos 配置中心动态刷新测试接口。
*
* @RefreshScope:
* 当配置发生变化并触发刷新事件后,
* 当前 Bean 会重新创建。
*
* Bean 重新创建时,
* @Value 会重新从 Spring Environment 读取最新配置。
*/
@RefreshScope
@RestController
@RequestMapping("/config")
public class ConfigController {
@Value("${biz.version:local-default}")
private String bizVersion;
@GetMapping("/version")
public Result<String> version() {
return Result.success(bizVersion);
}
}
15. 验证动态刷新成功
先重启 cloud-user。
当前 Nacos 配置:
yaml
biz:
version: v2
访问:
http
GET http://localhost:9200/config/version
返回:
json
{
"code": 0,
"message": "success",
"data": "v2"
}
如图↓

然后不重启服务,将 Nacos 配置改为:
yaml
biz:
version: v3

再次访问:
http
GET http://localhost:9200/config/version
返回:
json
{
"code": 0,
"message": "success",
"data": "v3"
}
说明:
text
动态刷新成功

16. Nacos 配置读取完整链路
这是本章最重要的原理部分。
16.1 启动阶段链路
text
Spring Boot 启动
↓
bootstrap 上下文初始化
↓
读取 bootstrap.yml
↓
获得:
spring.application.name
spring.profiles.active
Nacos Server 地址
Group
Namespace
文件扩展名
↓
Nacos Config Starter 创建配置客户端
↓
客户端连接 Nacos Server
↓
根据规则定位远程配置:
Namespace + Group + DataId
↓
拉取配置内容
↓
将远程配置转换为 PropertySource
↓
加入 Spring Environment
↓
Spring 创建业务 Bean
↓
@Value 从 Environment 解析配置
16.2 当前 cloud-user 的实际定位
text
Namespace:public
Group:DEFAULT_GROUP
DataId:cloud-user-dev.yaml
16.3 动态刷新链路
text
Nacos 控制台发布配置
↓
Nacos Server 保存新配置
↓
客户端监听到配置变化
↓
客户端拉取最新配置
↓
更新 Spring Environment
↓
触发刷新事件
↓
RefreshScope 清理旧 Bean 缓存
↓
下次访问时重新创建 Bean
↓
@Value 重新读取最新值
一句话总结:
text
Nacos Config 负责更新 Environment;
@RefreshScope 负责让 Bean 重新读取最新配置。
17. 长轮询还是长连接
学习 Nacos 配置刷新时,经常看到:
text
长轮询
需要注意版本差异。
Nacos 1.x
常见机制:
text
长轮询
Nacos 2.x
更强调:
text
长连接
当前使用:
text
Nacos Server 2.2.0
因此更准确的理解是:
text
客户端持续订阅配置变化;
服务端配置更新后,
客户端能够及时感知并重新拉取最新内容。
不要机械地背:
text
Nacos 配置刷新永远等于长轮询
18. cloud-product 接入配置中心
18.1 添加依赖
在 cloud-product/pom.xml 中加入:
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
18.2 创建 bootstrap.yml
yaml
spring:
application:
name: cloud-product
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
group: DEFAULT_GROUP
18.3 创建 Nacos 配置
text
DataId:cloud-product-dev.yaml
Group:DEFAULT_GROUP
内容:
yaml
biz:
version: product-v1
18.4 创建 ConfigController
java
package com.example.cloud.product.controller;
import com.example.cloud.common.result.Result;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RefreshScope
@RestController
@RequestMapping("/config")
public class ConfigController {
@Value("${biz.version:local-default}")
private String bizVersion;
@GetMapping("/version")
public Result<String> version() {
return Result.success(bizVersion);
}
}
访问:
http
GET http://localhost:9300/config/version
返回:
text
product-v1
修改 Nacos 配置为:
text
product-v2
不重启服务,再次访问,返回:
text
product-v2
19. cloud-order 接入配置中心
19.1 添加依赖
在 cloud-order/pom.xml 中加入:
xml
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-bootstrap</artifactId>
</dependency>
19.2 创建 bootstrap.yml
yaml
spring:
application:
name: cloud-order
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
group: DEFAULT_GROUP
19.3 创建 Nacos 配置
text
DataId:cloud-order-dev.yaml
Group:DEFAULT_GROUP
内容:
yaml
biz:
version: order-v1
19.4 创建 ConfigController
java
package com.example.cloud.order.controller;
import com.example.cloud.common.result.Result;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RefreshScope
@RestController
@RequestMapping("/config")
public class ConfigController {
@Value("${biz.version:local-default}")
private String bizVersion;
@GetMapping("/version")
public Result<String> version() {
return Result.success(bizVersion);
}
}
访问:
http
GET http://localhost:9400/config/version
返回:
text
order-v1
20. 创建 dev Namespace
进入 Nacos 控制台:
text
命名空间
↓
新建命名空间
填写:
text
命名空间名:dev
描述:开发环境
创建后记录:
text
Namespace ID
注意:
text
bootstrap.yml 中填写的是 Namespace ID,
不是显示名称 dev。


21. 在 dev Namespace 中创建三份配置
切换到:
text
dev
Namespace。

创建:
cloud-user-dev.yaml
yaml
biz:
version: user-dev-v1

cloud-product-dev.yaml
yaml
biz:
version: product-dev-v1
cloud-order-dev.yaml
yaml
biz:
version: order-dev-v1
Group 均为:
text
DEFAULT_GROUP
建好后如图↓

22. 三个服务切换到 dev Namespace
以 cloud-user/bootstrap.yml 为例:
yaml
spring:
application:
name: cloud-user
profiles:
active: dev
cloud:
nacos:
config:
server-addr: 127.0.0.1:8848
file-extension: yaml
group: DEFAULT_GROUP
# 注意:填写 Namespace ID,不是名称。
namespace: 你的-dev-Namespace-ID

同样修改:
text
cloud-product/bootstrap.yml
cloud-order/bootstrap.yml
23. 为什么修改 Namespace 后必须重启
动态刷新的前提是:
text
应用已经订阅了某一份配置
例如:
text
Namespace:public
Group:DEFAULT_GROUP
DataId:cloud-user-dev.yaml
当修改 Namespace 时,相当于切换到另一套配置集合。
这不是普通业务值变化,而是:
text
配置定位规则发生变化
因此需要重启服务,让 bootstrap 阶段重新执行。
24. Namespace 环境隔离验证
重启:
text
CloudUserApplication
CloudProductApplication
CloudOrderApplication
分别访问:
http
GET http://localhost:9200/config/version
GET http://localhost:9300/config/version
GET http://localhost:9400/config/version



返回:
text
cloud-user → user-dev-v1
cloud-product → product-dev-v1
cloud-order → order-dev-v1
说明三个服务已经成功读取:
text
dev Namespace
中的配置。
25. 为什么不把重复依赖全部放入 cloud-common
三个业务服务都引入了很多类似依赖:
text
spring-boot-starter-web
mybatis-plus-boot-starter
mysql-connector-java
nacos-discovery
nacos-config
spring-cloud-starter-bootstrap
看起来似乎可以全部放进:
text
cloud-common
但不推荐。
25.1 cloud-common 应保持职责单一
当前 cloud-common 主要提供:
text
统一返回 Result
错误码 ErrorCode
业务异常 BizException
全局异常处理器
它应该是公共基础库。
25.2 依赖具有传递性
如果 cloud-common 引入:
text
MyBatis-Plus
MySQL Driver
Nacos Config
所有依赖 cloud-common 的模块都会被动拿到这些依赖。
例如:
text
cloud-gateway
通常不需要 MyBatis-Plus 和 MySQL Driver。
25.3 Starter 可能触发自动配置
Spring Boot Starter 不只是普通 jar。
引入 Starter 后,可能触发:
text
数据源初始化
Bean 自动注册
配置加载
不需要数据库的模块如果被动拿到数据库 Starter,可能出现:
text
启动失败
依赖树混乱
无意义自动配置
25.4 推荐做法
text
父工程:
统一版本
cloud-common:
公共代码
各业务模块:
按需引入依赖
一句话总结:
text
版本统一放父工程;
公共代码放 cloud-common;
功能依赖由各模块按需声明。
未来如果重复依赖很多,可以考虑封装:
text
自定义 Starter
但学习阶段暂时没有必要。
26. @Value 与 @ConfigurationProperties
本章为了直观演示,使用:
java
@Value("${biz.version:local-default}")
当配置项很多时,不建议大量使用 @Value。
例如:
yaml
order:
timeout-seconds: 30
max-retry-count: 3
auto-cancel-enabled: true
更适合使用:
java
@ConfigurationProperties(prefix = "order")
优点:
text
配置集中
类型明确
便于校验
更容易维护
本章使用 @Value,是因为它更适合演示动态刷新链路。
27. 本章常见问题
27.1 bootstrap.yml 是不是优先级最高?
不是。
更准确的理解:
text
bootstrap.yml 加载得更早,
主要用于启动早期配置。
27.2 为什么普通 Bean 不会自动刷新 @Value?
因为 Bean 创建时已经注入过值。
后续 Environment 更新,并不会自动重新创建普通 Bean。
27.3 @RefreshScope 做了什么?
text
清理旧 Bean 缓存
↓
下次访问时重新创建 Bean
↓
重新解析 @Value
27.4 Namespace 为什么要填写 ID?
因为配置客户端定位 Namespace 时使用的是:
text
Namespace ID
不是界面显示名称。
27.5 Group 当前为什么保持 DEFAULT_GROUP?
当前服务数量少。
先保持简单,避免无意义复杂度。
27.6 配置中心和注册中心是否必须使用同一个 Nacos Server?
学习环境中通常使用同一个 Nacos Server。
但逻辑上,它们是两个独立能力。
27.7 配置中心概念与链路

28. 本章结论
本章完成:
text
Nacos Config 依赖接入
spring-cloud-starter-bootstrap
bootstrap.yml
DataId
Group
Namespace
配置启动加载
配置动态监听
普通 Bean 刷新失败故障演练
@RefreshScope 修复
三个服务接入配置中心
dev Namespace 环境隔离
配置加载与刷新链路分析
当前项目已经具备:
text
服务注册
配置集中管理
配置动态刷新
环境隔离
下一章将进入:
text
第 7 章:OpenFeign 服务调用
下一章会完成:
text
订单服务调用用户服务
订单服务调用商品服务
OpenFeign 接口定义
服务名调用
负载均衡
远程商品校验
远程库存扣减
远程调用失败排查
错误注册 IP 故障演练
Nacos 停止后的远程调用行为观察