Files
common/consul/配置中心方案.md
2026-03-12 08:51:13 +08:00

269 lines
9.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Consul KV 配置中心方案
**文档版本**v1.0
**创建日期**2025-12-16
**负责项目**customerservice + message + gateway
---
## 一、核心目标
| 目标 | 说明 |
|------|------|
| **安全性** | 敏感配置(连接地址/密码)不写在代码里,从 Consul KV 读取 |
| **回退机制** | Consul 不可用时,使用本地默认配置保证服务可启动 |
| **热更新** | Consul KV 变更后,服务无需重启立即生效 |
| **性能最优** | 请求路径只读内存(原子快照),不访问 Consul单协程阻塞监听不空转 |
---
## 二、配置分类与热更新策略
### 2.1 配置分类
| 分类 | 配置项 | 热更新方式 |
|------|--------|------------|
| **连接池配置** | http 连接池数量、redis 连接池数量、mongo 连接池数量 | 平滑切换(创建新池→原子替换→延迟关闭旧池) |
| **协程池配置** | grpool worker 数量 | 动态调整(`grpool.SetSize()` |
| **业务参数** | 追问延时、归档延时、批量大小、超时时间、卡片触发轮数 | 直接原子更新内存变量 |
| **开关/限流** | 功能开关、限流阈值、日志级别 | 直接原子更新内存变量 |
| **中间件地址** | Redis/MQ/Mongo/ES/Jaeger 地址 | 平滑切换连接池 |
### 2.2 热更新策略矩阵
```
┌─────────────────────────────────────────────────────────────────┐
│ 热更新策略矩阵 │
├─────────────────────────────────────────────────────────────────┤
│ 配置变更类型 │ 更新方式 │ 对请求影响 │
├─────────────────────────────────────────────────────────────────┤
│ 业务参数/开关 │ atomic.Value │ 无影响,立即生效 │
│ 协程池数量 │ grpool.SetSize │ 无影响,渐进生效 │
│ 连接池数量/地址 │ 平滑切换单例 │ 无影响,新请求用新池 │
└─────────────────────────────────────────────────────────────────┘
```
---
## 三、Consul KV 键名规范
```
config/{service}/pool
config/{service}/business
config/{service}/middleware
```
### 3.1 示例 KV 结构
**Key**: `config/customerservice/pool`
```yaml
http:
maxConns: 100 # HTTP 连接池最大连接数
maxIdleConns: 20 # HTTP 连接池最大空闲连接
redis:
maxActive: 50 # Redis 连接池最大活跃连接
maxIdle: 10 # Redis 连接池最大空闲连接
idleTimeout: 300 # 空闲超时(秒)
grpool:
workerSize: 200 # 协程池 worker 数量
```
**Key**: `config/customerservice/business`
```yaml
followUp:
delay1: 30 # 第一次追问延时(秒)
delay2: 60 # 第二次追问延时(秒)
delay3: 180 # 第三次追问延时(秒)
archive:
delay: 3600 # 归档延时(秒)
stream:
batchSize: 200 # 批量读取消息数量
blockTimeout: 2000 # 阻塞超时(毫秒)
card:
triggerCount: 5 # 触发发送卡片的对话轮数
```
**Key**: `config/customerservice/middleware`
```yaml
redis:
address: "192.168.3.200:6379"
password: ""
db: 0
rabbitmq:
host: "192.168.3.200"
port: 5672
username: "guest"
password: "guest"
vhost: "/"
mongo:
uri: "mongodb://192.168.3.200:27017"
database: "customer_service"
```
---
## 四、架构设计
### 4.1 模块结构
consul api 里有个watch , 用watch去做
```
common/configcenter/
├── configcenter.go # 核心:启动/停止/获取配置
├── watcher.go # Consul KV 阻塞监听(单协程)
├── snapshot.go # 配置快照atomic.Value
├── hook.go # 变更回调分发
└── types.go # 配置结构体定义
```
### 4.2 核心接口
```go
// 启动配置中心(每个服务 main.go 调用一次)
func Start(ctx context.Context, opts Options) error
// 获取当前配置快照请求路径调用O(1) 无锁)
func Get() *Snapshot
// 注册变更回调(组件注册自己的重初始化逻辑)
func Subscribe(name string, handler func(old, new *Snapshot))
// 优雅停止
func Stop()
```
### 4.3 数据流
```
┌──────────────┐ 阻塞查询 ┌──────────────┐
│ Consul KV │ ─────────────→ │ Watcher │ (单协程,不空转)
└──────────────┘ (长轮询) └──────┬───────┘
│ 配置变更
┌──────────────┐
│ Snapshot │ atomic.Value 原子替换)
└──────┬───────┘
┌───────────────────────┼───────────────────────┐
▼ ▼ ▼
┌────────────────┐ ┌────────────────┐ ┌────────────────┐
│ 业务代码读取 │ │ Hook 回调 │ │ 日志记录 │
│ Get().Pool │ │ 重建连接池 │ │ 版本号变更 │
└────────────────┘ └────────────────┘ └────────────────┘
```
---
## 五、服务启动流程
```go
func main() {
ctx := context.Background()
// 1. 启动配置中心(优先从 Consul 拉取,失败则用本地默认)
if err := configcenter.Start(ctx, configcenter.Options{
ConsulAddr: "192.168.3.200:8500",
ServiceName: "customerservice",
DefaultPath: "config.yml", // 回退配置
}); err != nil {
glog.Warningf(ctx, "配置中心启动失败,使用本地配置: %v", err)
}
// 2. 注册组件热更新回调
configcenter.Subscribe("redis", redis.OnConfigChange)
configcenter.Subscribe("grpool", ragflow.OnPoolSizeChange)
configcenter.Subscribe("rabbitmq", rabbitmq.OnConfigChange)
// 3. 初始化组件(使用 configcenter.Get() 获取配置)
initComponents(ctx)
// 4. 启动服务...
// 5. 优雅退出
defer configcenter.Stop()
}
```
---
## 六、性能保证
| 环节 | 性能策略 |
|------|----------|
| **请求路径** | 只读 `atomic.Value`O(1),无锁,无网络 |
| **监听 Consul** | 阻塞查询Blocking Query无变更时不消耗 CPU |
| **配置解析** | 只在变更时解析一次 YAML → 结构体 |
| **连接池切换** | 原子替换指针,旧池延迟 30s 关闭(等待请求完成) |
| **协程池调整** | `grpool` 内置支持动态调整,无需重建 |
---
## 七、回退与容错
| 场景 | 处理方式 |
|------|----------|
| **启动时 Consul 不可用** | 使用本地 `config.yml` 默认配置,服务正常启动 |
| **运行时 Consul 断连** | 保持最后一次成功配置,自动重试连接 |
| **配置格式错误** | 拒绝更新,保持旧配置,记录错误日志 |
| **连接池切换失败** | 保持旧连接池,记录错误,不影响服务 |
---
## 八、Consul KV 操作示例
### 8.1 通过 Consul UI 操作
1. 访问 `http://192.168.3.200:8500/ui`
2. 点击 **Key/Value** 菜单
3. 创建/编辑 Key`config/customerservice/business`
4. 在 Value 中粘贴 YAML 配置内容
5. 点击 **Save**
### 8.2 通过 CLI 操作
```bash
# 写入配置
consul kv put config/customerservice/business @business.yml
# 读取配置
consul kv get config/customerservice/business
# 删除配置
consul kv delete config/customerservice/business
```
### 8.3 通过 HTTP API 操作
```bash
# 写入配置
curl --request PUT \
--url http://192.168.3.200:8500/v1/kv/config/customerservice/business \
--data-binary @business.yml
# 读取配置Base64 编码)
curl http://192.168.3.200:8500/v1/kv/config/customerservice/business
# 阻塞查询(长轮询,等待变更)
curl "http://192.168.3.200:8500/v1/kv/config/customerservice/business?index=123&wait=5m"
```
---
## 九、实现进度
| 阶段 | 状态 | 说明 |
|------|------|------|
| 方案设计 | ✅ 完成 | 本文档 |
| common/configcenter 模块 | ⏳ 待实现 | 核心配置中心模块 |
| 各组件热更新回调 | ⏳ 待实现 | Redis/MQ/Mongo/ES 等 |
| 联调验证 | ⏳ 待实现 | KV 修改后无需重启生效 |
---
## 十、注意事项
1. **安全性**:生产环境的 Consul 必须启用 ACL限制 KV 访问权限
2. **版本控制**:重要配置变更前,建议先备份旧配置
3. **灰度发布**:可通过 `config/{env}/{service}` 实现多环境配置隔离
4. **监控告警**:建议对配置变更事件添加日志和告警