Files
Edu/docs/architecture/runbooks/p6-hardening.md
SpecialX e9ea34fe53
Some checks failed
CI Go / test (push) Has been cancelled
CI Python / test (push) Has been cancelled
CI TypeScript / test (push) Has been cancelled
CI Proto / lint (push) Failing after 8m7s
feat(p6): production hardening with circuit breaker, backup, monitoring and chaos engineering
P6 生产硬化阶段交付物(46 文件):

## 1. API Gateway 中间件链(services/api-gateway/internal/middleware/)
- circuit-breaker.go: gobreaker v2 熔断器(5s 窗口/50% 错误率/30s OPEN→HALF_OPEN)
- ratelimit.go: 令牌桶限流(sync.Map + cleanup goroutine,默认 100rps/20 burst)
- cors.go: CORS 中间件(CORS_ORIGINS 环境变量)
- recovery.go: panic 恢复 + uuid request_id
- security.go: 安全头 + 请求体 10MB 限制
- requestid.go: 请求 ID 注入
- health/health.go: /healthz + /readyz 健康检查
- main.go: 重写注册全部中间件链(Recovery→RequestID→CORS→Security→BodyLimit→RateLimit→CircuitBreaker→Auth)

## 2. 基础设施硬化(infra/)
- backup/backup-mysql.sh: MySQL 全量备份(mysqldump+gzip,按服务独立)
- backup/restore-mysql.sh: 恢复脚本
- backup/backup-cron.sh: cron 调度入口(5 服务批量备份)
- alertmanager/alertmanager.yml: 告警路由(webhook + 邮件示例)
- prometheus/rules.yml: 8 条告警规则(服务可用性/性能/资源 3 组)
- grafana/dashboards/microservices-overview.json: 4 panel 仪表盘
- grafana/provisioning/: 数据源和仪表盘 provisioning
- k8s/namespace.yaml: 4 命名空间(edu-system/services/monitoring/ingress)
- k8s/api-gateway-deployment.yaml: Deployment + Service 骨架
- chaos/experiments.yaml: 3 个 Litmus 混沌实验(pod-kill/network-latency/disk-fill)
- docker-compose.monitoring.yml: 监控栈 profile
- security/secrets.example.env: 8 项密钥占位符
- security/waf-rules.conf: ModSecurity WAF 规则骨架

## 3. 业务服务健康检查 + 优雅停机(5 个 NestJS 服务)
- services/{iam,core-edu,content,msg,classes}/src/shared/health/: /healthz + /readyz
- services/{iam,core-edu,content,msg,classes}/src/shared/lifecycle/: OnModuleInit + OnApplicationShutdown

## 4. Python 服务健康检查
- services/{ai,data-ana}/src/health/health.py: FastAPI APIRouter

## 5. 运维文档
- docs/architecture/runbooks/p6-hardening.md: P6 总览 Runbook(9 章节)
- docs/architecture/runbooks/incident-response.md: 事件响应手册(5 章节)
- docs/architecture/004-p6-addendum.md: 004 架构补记 P6 章节
- docs/troubleshooting/known-issues-p6-addendum.md: 15 条 P6 场景→技术映射

## 验收信号
- RPO ≤ 15min(MySQL 备份 + binlog PITR)
- RTO ≤ 30min(K8s 滚动更新 + DNS 切换)
- P99 ≤ 500ms(熔断 + 限流 + 缓存)
- 熔断器错误率 > 50% 触发 OPEN
- 限流 100rps/20 burst
- 备份保留 7 天
- 混沌实验每月 1 次
2026-07-08 02:16:58 +08:00

8.9 KiB
Raw Permalink Blame History

P6 生产硬化 Runbook

阶段P6 生产硬化 目标指标RPO ≤ 15minRTO ≤ 30minP99 ≤ 500ms 维护者SRE 团队 关联文档:docs/architecture/004_architecture_impact_map.mddocs/architecture/roadmap/tech-debt.mddocs/architecture/runbooks/incident-response.md

1. 概览

P6 阶段围绕"稳定、可观测、可恢复"三大主题,对业务服务进行生产硬化,确保系统在流量峰值、依赖故障、区域级灾难下仍能满足核心 SLO。

1.1 目标指标

指标 目标 度量来源
RPO恢复点目标 ≤ 15 分钟 备份调度日志 + WAL 位点
RTO恢复时间目标 ≤ 30 分钟 故障注入演练计时
P99 延迟 ≤ 500 ms Prometheus http_request_duration_seconds
可用性 ≥ 99.9% 多区域健康探针汇总
错误率 ≤ 0.1% Gateway 5xx 比率

1.2 交付物清单

  • API Gateway 熔断/限流中间件Gogobreaker v2 + token bucket
  • 备份与恢复脚本(scripts/backup/scripts/restore/
  • Prometheus 告警规则 + Alertmanager 路由配置
  • Grafana 仪表盘服务总览、SLO、依赖健康
  • 混沌工程实验库(chaos/
  • K8s 部署 manifestdeploy/k8s/
  • 健康检查标准化(/healthz/readyz
  • 优雅停机(lifecycle.service.ts + app.enableShutdownHooks()

2. 熔断与限流

2.1 中间件使用

API GatewayGo在路由链路上统一接入

  • 熔断器:github.com/sony/gobreaker/v2,按下游服务维度建桶
  • 限流:基于 sync.Map 的令牌桶,按 route + tenant 维度限流

熔断器配置示例(伪代码):

cb := gobreaker.NewCircuitBreaker[any](gobreaker.Settings{
  Name:        "core-edu",
  MaxRequests: 5,                  // 半开态最大试探请求
  Interval:    60 * time.Second,   // 计数窗口
  Timeout:     30 * time.Second,   // 开启态冷却
  ReadyToTrip: func(c gobreaker.Counts) bool {
    return c.ConsecutiveFailures > 5 || c.TotalFailures/c.TotalRequests > 0.5
  },
})

2.2 参数调优

参数 默认 推荐范围 调优依据
MaxRequests半开试探 5 3-10 下游恢复速度
Timeout冷却 30s 10-60s 下游故障平均恢复时间
ConsecutiveFailures 5 3-10 误报容忍度
限流 QPS租户级 1000 500-5000 租户 SLA 等级
桶清理周期 60s 30-120s 内存占用与精度权衡

2.3 故障演练流程

  1. 在预发环境注入下游延迟tc/netem 500ms+
  2. 观察熔断器状态切换Closed → Open → Half-Open → Closed
  3. 验证限流桶在窗口边界正确清理sync.Map + ticker
  4. 记录 P99 与错误率到演练报告
  5. 回滚注入:./chaos/rollback.sh <experiment>

3. 备份与恢复

3.1 备份脚本

  • 位置:scripts/backup/backup-cron.sh
  • 调度K8s CronJob每 15 分钟一次(满足 RPO ≤ 15min
  • 内容PostgreSQL 全量 + WAL 归档 + Redis RDB + Kafka topic offset 快照
  • 产物写入对象存储MinIO/S3保留策略 7d日备 30d

执行:

./scripts/backup/backup-cron.sh --service iam --type full
./scripts/backup/backup-cron.sh --service iam --type incr

3.2 恢复演练流程

  1. 在隔离环境拉起空集群
  2. 执行 ./scripts/restore/restore.sh --service <svc> --backup-id <id>
  3. 校验数据一致性(行数、最新位点、校验和)
  4. 记录恢复耗时,验证 RTO ≤ 30min
  5. 演练频率:每月一次

3.3 RPO 验证方法

  • 对比最近一次备份时间与当前时间差
  • 查询 backup_loglast_success_at 字段
  • 告警:连续 2 个周期30min未成功备份 → P1

4. 监控告警

4.1 Prometheus 规则

位置:deploy/observability/prometheus/rules/

关键规则:

  • HighErrorRate5xx 比率 > 1% 持续 5min
  • HighLatencyP99P99 > 500ms 持续 5min
  • CircuitBreakerOpen:熔断器处于 Open 态 > 1min
  • BackupStale:备份超过 30min 未成功
  • DBConnectionsExhausted:连接池使用率 > 90%
  • KafkaConsumerLag:消费堆积 > 10000 持续 5min

4.2 Alertmanager 路由

  • P0/P1 → PagerDuty + 电话
  • P2 → 飞书群 + 邮件
  • P3 → 飞书群
  • 抑制:同一服务 5min 内同告警只发一次inhibit + group_by

4.3 Grafana 仪表盘

仪表盘 用途 关键面板
Service Overview 服务总览 QPS、P99、错误率、熔断状态
SLO Dashboard SLO 跟踪 可用性、错误预算消耗
Dependency Health 依赖健康 DB/Redis/Kafka 连接与延迟
Backup Status 备份状态 最近备份、RPO、恢复演练

5. 混沌工程

5.1 实验清单

实验 注入方式 预期表现 频率
DB 主节点宕机 kill postgres 自动故障转移RTO<30min
Redis 不可达 iptables 拒绝 降级到本地缓存
Kafka broker 宕机 kill broker 生产重试,消费堆积可控
下游服务延迟 tc netem +500ms 熔断器打开,错误率<1%
网络分区 iptables 隔离 多可用区切换
磁盘满 fill disk 告警触发,写入降级

5.2 执行流程

  1. 选择实验 → 在 chaos/ 选择对应 YAML
  2. 预检:确认告警通道、回滚脚本就绪
  3. 执行:kubectl apply -f chaos/<experiment>.yaml
  4. 观察Grafana + 日志
  5. 回滚:./chaos/rollback.sh <experiment>
  6. 复盘:记录到 docs/architecture/runbooks/incident-response.md

6. 安全加固

6.1 WAF 规则

  • SQL 注入、XSS 模式匹配
  • 路径穿越、命令注入
  • 限速:单 IP > 100req/s 拦截
  • 地域封禁(按需)

6.2 密钥管理

  • 密钥存储K8s Secret + 外部 KMSVault
  • 轮换DB 密码每 90 天JWT 签名密钥每 180 天
  • 注入:通过环境变量 / 挂载卷,禁止入镜像
  • 审计:所有密钥访问记录到 audit log

6.3 CORS 策略

  • 允许来源:白名单域名(生产环境严格)
  • 允许方法GET/POST/PUT/PATCH/DELETE
  • 凭证允许Cookie
  • 预检缓存600s

7. K8s 部署

7.1 Manifest 说明

位置:deploy/k8s/,每个服务一组 manifest

  • deployment.yaml:副本数、资源、探针、优雅停机
  • service.yamlClusterIP
  • hpa.yamlCPU>70% 扩容min=3 max=20
  • poddisruptionbudget.yamlminAvailable=2
  • networkpolicy.yaml:限制出向

探针配置:

livenessProbe:
  httpGet: { path: /healthz, port: 3000 }
  initialDelaySeconds: 15
  periodSeconds: 10
readinessProbe:
  httpGet: { path: /readyz, port: 3000 }
  initialDelaySeconds: 5
  periodSeconds: 5

优雅停机:

terminationGracePeriodSeconds: 60

7.2 Helm 化路线

  • P6原生 manifest快速验证
  • P7抽取 Helm Chartvalues.yaml 按环境区分
  • P8引入 Argo CD GitOps 自动同步

8. 灾难恢复

8.1 RTO/RPO 目标

场景 RTO RPO
单 Pod 故障 30s 0
单节点故障 2min 0
单可用区故障 10min 0
区域级灾难 30min 15min

8.2 多可用区策略

  • K8s 集群跨 3 可用区Pod 反亲和
  • DB 主从跨可用区同步复制
  • Redis 哨兵跨可用区
  • Kafka min.insync.replicas=2跨可用区 broker

8.3 DNS 切换

  • 区域级故障:通过全局 DNSCloudflare/Route53切换到备用区域
  • 健康检查:每 10s 探测,连续 3 次失败自动切换
  • TTL60s快速切换
  • 演练:每季度一次 DNS 切换演练

9. 故障排查

现象 可能原因 排查步骤 解决方案
5xx 激增 下游服务故障 查 Grafana 熔断状态、下游健康 确认熔断器已打开,扩容下游
P99 升高 DB 慢查询/连接耗尽 查 PG 慢日志、连接池 加索引/扩连接池/限流
消费堆积 消费者慢/宕机 查 Kafka lag、消费者日志 扩消费者、修 bug
备份失败 存储/网络/凭证 查 backup-cron 日志 修凭证、清理旧备份
健康检查失败 DB 不可达 查 DB 状态、网络 故障转移、恢复 DB
Pod 频繁重启 OOM/探针失败 查 kubectl describe、内存 调资源/修探针
熔断不恢复 下游未恢复 查 Half-Open 试探结果 修复下游、调 Timeout
限流误杀 桶配置过低 查限流日志、QPS 调高桶容量
DNS 切换无效 TTL 缓存 查 DNS 解析链 等待 TTL / 清缓存
跨区延迟高 跨区流量 查网络拓扑 调亲和性就近访问

附录:关联文档

  • 架构影响地图:docs/architecture/004_architecture_impact_map.md
  • P6 架构补记:docs/architecture/004-p6-addendum.md
  • 事件响应:docs/architecture/runbooks/incident-response.md
  • 已知问题:docs/troubleshooting/known-issues.md
  • P6 已知问题补丁:docs/troubleshooting/known-issues-p6-addendum.md
  • 技术债务:docs/architecture/roadmap/tech-debt.md