Files
Edu/docs/architecture/runbooks/incident-response.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

172 lines
4.8 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.
# 事件响应手册
> 目标:规范生产事件的分级、响应、处置与复盘,确保 RTO ≤ 30min
> 关联:`docs/architecture/runbooks/p6-hardening.md`
## 1. 事件分级
| 级别 | 定义 | 影响 | 响应时效 | 升级 |
|------|------|------|----------|------|
| P0 | 全站不可用 / 核心数据损坏 | 全部用户 | 5 分钟内响应 | 立即升级至 CTO |
| P1 | 核心功能不可用 / 关键 SLO 破坏 | 大量用户 | 10 分钟内响应 | 升级至服务负责人 |
| P2 | 部分功能降级 / 非核心故障 | 部分用户 | 30 分钟内响应 | 服务负责人跟进 |
| P3 | 单点告警 / 潜在风险 | 少量/无用户 | 工作时间内响应 | On-Call 自行处理 |
### 1.1 分级示例
- P0网关全挂、主 DB 不可用且无法故障转移、数据丢失超过 RPO
- P1登录不可用、课程播放不可用、Kafka 生产阻塞
- P2消息推送延迟、报表生成失败、单个非核心服务宕机
- P3单 Pod 重启、磁盘使用率告警、慢查询告警
## 2. 响应流程
```
发现 → 确认 → 升级 → 处理 → 恢复 → 复盘
```
### 2.1 发现
- 告警来源Prometheus / Alertmanager / 用户反馈 / 人工巡检
- 第一动作:在 On-Call 群贴告警,标注收到时间
### 2.2 确认
- On-Call 5 分钟内确认告警真实性
- 排除误报(探针抖动、已知维护窗口)
- 初步定级创建事故工单Jira / 飞书项目)
### 2.3 升级
- 超出处置能力 → 立即升级
- P0/P1 → 拉事故群,通知相关服务 Owner
- 涉及外部公告 → 通知客服与公关
### 2.4 处理
- 遵循"先恢复,后定位"原则
- 优先使用预案:回滚、扩容、降级、熔断、切换
- 每个操作记录时间戳与执行人
- 关键决策需事故指挥确认
### 2.5 恢复
- 健康检查通过、SLO 恢复
- 观察 15 分钟确认稳定
- 关闭事故工单,进入复盘
### 2.6 复盘
- 48 小时内提交复盘报告
- 无 blame 文化:对事不对人
- 输出改进项,录入 `docs/architecture/roadmap/tech-debt.md`
## 3. On-Call 轮值
### 3.1 轮值制度
- 主备双人轮值,每周轮换
- 工作日9:00-21:00 主,其余备
- 节假日:全天主备
- 交接:周一 10:00 站会交接,遗留问题清单
### 3.2 联络方式
- 电话:主 + 备 + 升级链
- 即时通讯:飞书 On-Call 群
- 告警PagerDuty / 飞书机器人
### 3.3 响应要求
- P0/P1电话 5 分钟内接听
- 告警确认:群内 5 分钟内回复
- 无法响应:自动升级至备值
## 4. 沟通模板
### 4.1 事故通报(初报)
```
【事故通报】<P级别> - <简述>
时间:<YYYY-MM-DD HH:MM>
级别:<P0/P1/P2/P3>
影响:<受影响功能/用户范围>
现状:<已知信息>
负责人:<On-Call>
下一步:<计划动作>
```
### 4.2 进展更新(每 30 分钟或重大变化)
```
【进展更新】<事故标题>
时间:<HH:MM>
进展:<自上次以来发生/完成的事>
当前状态:<仍受影响的功能>
下一步:<接下来 30 分钟计划>
```
### 4.3 恢复通知
```
【恢复通知】<事故标题>
恢复时间:<HH:MM>
持续时长:<时长>
原因:<根因摘要>
影响:<最终影响评估>
后续:<复盘会时间>
```
### 4.4 复盘报告
```
【复盘报告】<事故标题>
时间:<起止时间>
级别:<P级别>
影响:<用户/功能/数据>
时间线:<关键事件时间轴>
根因:<5why 分析>
处置:<做了什么、有效/无效>
改进项:<TODO + 负责人 + 截止>
经验:<可沉淀到 known-issues / runbook 的内容>
```
## 5. 常见事故处置
### 5.1 DB 主从切换
1. 确认主库故障(健康检查、连接超时)
2. 触发自动故障转移Patroni / Orchestrator
3. 若自动失败,手动 `./scripts/db/failover.sh --service <svc>`
4. 更新连接配置 / 刷新连接池
5. 验证读写正常、数据位点
6. 旧主恢复后作为从库加入
### 5.2 Kafka 消费堆积
1. 查看堆积:`kubectl exec -- kafka-consumer-lag`
2. 定位慢消费者查日志、trace
3. 扩容消费者副本HPA 或手动)
4. 若处理逻辑慢:临时降级非核心处理
5. 堆积消化后恢复
6. 复盘:扩容阈值、消费者并发配置
### 5.3 服务雪崩
1. 确认雪崩源头(哪个下游故障)
2. 确认熔断器已打开Gateway 状态)
3. 若未打开:手动 `./scripts/gateway/circuit-breaker.sh open <service>`
4. 降级非核心功能
5. 扩容上游服务应对重试流量
6. 修复下游、半开试探、逐步恢复
7. 复盘:熔断参数、依赖隔离
## 附录:升级链
| 级别 | 第一响应 | 升级 1 | 升级 2 | 升级 3 |
|------|----------|--------|--------|--------|
| P0 | On-Call | 服务负责人 | 架构负责人 | CTO |
| P1 | On-Call | 服务负责人 | 架构负责人 | - |
| P2 | On-Call | 服务负责人 | - | - |
| P3 | On-Call | - | - | - |