分布式配置中心设计
问题
如何设计分布式配置中心,实现配置的集中管理、动态刷新和灰度发布?
答案
为什么需要配置中心
| 问题 | 传统方式 | 配置中心 |
|---|---|---|
| 配置散落 | 各服务本地文件 | 统一管理 |
| 修改需重启 | 改配置重启服务 | 动态刷新 |
| 多环境管理 | 手动维护多份 | 环境隔离 |
| 灰度发布 | 不支持 | 灰度规则配置 |
| 配置审计 | 无 | 变更历史记录 |
主流配置中心对比
| 特性 | Nacos | Apollo | Spring Cloud Config |
|---|---|---|---|
| 开源方 | 阿里巴巴 | 携程 | Spring |
| 配置管理 | ✅ | ✅ | ✅ |
| 服务发现 | ✅ | ❌ | ❌ |
| 实时推送 | 长轮询 / gRPC | 长轮询 + 通知 | Git Webhook / Bus |
| 灰度发布 | ✅ | ✅ | ❌ |
| 多环境 | namespace + group | env + cluster | profile + label |
| 管理界面 | ✅ | ✅(更强大) | ❌(需额外开发) |
| 配置回滚 | ✅ | ✅ | Git 回滚 |
选型建议
- 已用 Nacos 做注册中心,配置中心也用 Nacos(统一技术栈)
- 配置管理需求复杂(灰度、权限、审批),选 Apollo
- 极简场景 / Spring 技术栈,选 Spring Cloud Config
配置中心架构
Nacos 配置中心
bootstrap.yml — Nacos 配置
spring:
application:
name: order-service
cloud:
nacos:
config:
server-addr: nacos:8848
namespace: dev # 环境隔离
group: ORDER_GROUP # 业务分组
file-extension: yaml
# 共享配置
shared-configs:
- data-id: common-db.yaml
group: SHARED
refresh: true
动态刷新配置
@RestController
@RefreshScope // 配置变更时重新注入
public class OrderController {
@Value("${order.timeout:30}")
private int orderTimeout; // 支持动态更新
// 或者使用 @ConfigurationProperties
@Autowired
private OrderProperties orderProperties;
}
// 监听配置变更事件
@Component
public class ConfigChangeListener {
@NacosConfigListener(dataId = "order-service.yaml", groupId = "ORDER_GROUP")
public void onConfigChange(String config) {
log.info("配置变更: {}", config);
// 刷新本地缓存、连接池等
}
}
Apollo 配置管理
Apollo 的配置层级:
Application → Environment → Cluster → Namespace
(dev/uat/prod) (机房) (配置集)
Apollo 使用
// 方式1:注解
@ApolloConfig
private Config config;
@ApolloConfigChangeListener
private void onChange(ConfigChangeEvent event) {
for (String key : event.changedKeys()) {
ConfigChange change = event.getChange(key);
log.info("Key: {}, Old: {}, New: {}",
key, change.getOldValue(), change.getNewValue());
}
}
// 方式2:API
String value = ConfigService.getAppConfig().getProperty("key", "default");
动态刷新原理
灰度配置发布
灰度策略:
- 按 IP:指定灰度机器 IP
- 按标签:给实例打标签(canary=true)
- 按比例:10% → 50% → 100%
配置安全
| 策略 | 说明 |
|---|---|
| 加密存储 | 敏感配置(密码、密钥)加密存储,客户端解密 |
| 权限控制 | 不同团队只能修改自己的 namespace |
| 审批流程 | 生产环境配置变更需审批 |
| 变更审计 | 记录谁在什么时候改了什么 |
| 回滚能力 | 支持一键回滚到历史版本 |
常见面试问题
Q1: 配置中心挂了怎么办?
答案:
- 本地缓存:客户端缓存最近一次拉取的配置到本地文件
- 配置中心不可用时,使用本地缓存继续工作
- 配置中心恢复后,自动重新连接并同步
- Nacos / Apollo 都有本地快照机制
Q2: Nacos 的长轮询和 Apollo 的推拉结合有什么区别?
答案:
- Nacos 长轮询:客户端发起 HTTP 长轮询,服务端 hold 住请求(默认 29.5s),有变更立即返回
- Apollo 推拉结合:客户端维护长连接 + 服务端推送变更通知 + 客户端定时拉取兜底
- 两者都能做到秒级感知配置变更
Q3: 配置的优先级顺序是怎样的?
答案:
Spring Boot 配置优先级(从高到低):
- 命令行参数
- 远程配置中心
application-{profile}.ymlapplication.yml@PropertySource注解- 默认值
详见 Spring Boot 配置管理。
Q4: 如何做配置的多环境管理?
答案:
以 Nacos 为例:
- Namespace:环境隔离(dev / test / uat / prod)
- Group:业务分组(ORDER_GROUP / PAY_GROUP)
- DataId:具体配置文件(order-service.yaml)
不同环境的配置完全隔离,不会互相影响。参考 配置中心。