AI 学习笔记(二十二):LLM 自动止血与恢复验收最小实践
上一篇我们把 burn-rate 告警和 runbook 自动化串了起来。
但线上真正更难的,不是“能不能先止血”,而是:
系统什么时候可以自动降级,什么时候可以恢复放量,以及什么时候才算真正恢复。
很多团队的事故处理会卡在这里:
- 告警来了,先关功能、切 fallback、冻结发布
- 指标看起来回落了,于是大家觉得“差不多恢复了”
- 结果 20 分钟后问题复发,或者质量指标继续慢性失血
这篇继续生产运维主线,补上一个更完整的闭环:
把自动止血、恢复流程和恢复验收阈值做成可执行状态机。
先说结论:
- 自动止血解决的是“先别继续扩大损失”,不是“已经恢复”
- 恢复必须分阶段推进,不能从
readonly直接跳回full traffic - 只有恢复验收通过,系统才应该自动退出事故态
1. 为什么自动止血和恢复验收必须分开设计
很多团队已经会做自动止血,例如:
- 错误率飙高时自动切 provider fallback
- 高风险写操作自动转只读
- burn-rate 超阈值时自动冻结发布
这些动作都很有价值,但它们本质上只是 containment。
也就是:先把事故扩散速度压下来。
真正的恢复还要回答另外几个问题:
- 核心用户路径是否已经重新稳定
- 质量指标是否回到可接受区间
- 高风险副作用是否已经停止
- 恢复动作本身有没有引入新的债务或新瓶颈
如果没有这层验收,系统很容易陷入两种假恢复:
表面恢复
服务 200 了,但结构化输出质量、人工接管率、误调用率仍然失控脆弱恢复
只是靠极端降级把指标压住,一旦恢复流量或重新放开功能就再次恶化
所以自动化不能只设计“怎么止血”,还要定义“恢复完成”的硬门槛。
2. 最小状态机:把事故处理拆成 5 个明确阶段
一个适合 LLM 应用的最小状态机,可以先定义为 5 个阶段:
healthy
正常运行mitigating
进入自动止血,冻结高风险动作degraded
系统仍然可服务,但运行在受限模式recovering
开始小流量恢复、逐项验证verified
验收通过,退出事故态
核心不是名字,而是每个阶段的允许动作要不同。
例如:
1 | incident_state_machine: |
这样做的价值是:
- 自动化系统知道当前应该做什么
- 值班同学知道哪些动作仍然被禁止
- 事故复盘能明确卡在哪个阶段,而不是笼统说“恢复慢”
3. 自动止血先做什么:优先控制副作用和失血速度
进入 mitigating 阶段时,建议优先做下面几件事:
冻结高风险写操作
例如外呼、发消息、写工单、改数据库、执行 shell切 provider fallback
把异常 provider 的流量切走,或者收紧到稳定模型收缩上下文和工具范围
减少长上下文和大工具集带来的额外不确定性冻结发布
暂停 prompt / workflow / routing 配置变更生成 incident 记录
留下自动动作、触发原因和开始时间,避免后续无证据复盘
最常见的错误,是自动止血一上来就做“太聪明”的修复。
更稳的原则是:
先把副作用和继续失血的风险压住,再谈恢复。
这对 LLM 系统尤其重要,因为很多事故不是“服务彻底挂了”,而是:
- 能回答,但质量明显漂移
- 能调用工具,但副作用变多
- 能跑流程,但人工接管率突然飙升
这些情况最怕的不是短时不可用,而是静默继续扩大损失。
4. 恢复验收看什么:至少做 4 组验证
进入 recovering 后,不要只盯一个成功率图。
最小恢复验收,建议至少做下面 4 组验证。
1) 服务路径验证
确认核心链路已经能稳定完成:
- 主用户路径成功率回到阈值上方
- P95 / P99 延迟恢复到可接受区间
- provider fallback 不再频繁触发
2) 质量路径验证
对 LLM 应用来说,这往往比服务 200 更关键:
- 结构化输出成功率恢复
- 关键任务通过率恢复
- 人工接管率显著回落
3) 副作用验证
恢复期间要重点确认“坏事有没有继续发生”:
- 高风险写操作误触发为 0
- 敏感外呼、通知、工单、自动提交没有继续误发
- 回滚或降级动作没有留下脏状态
4) 稳定窗口验证
不要看到 5 分钟恢复就宣布结束。
建议至少要求:
- 在一个连续观察窗口内维持稳定
- 没有新的 P1/P2 告警
- 没有新的 burn-rate 升高信号
可以先从一个很实用的阈值表开始:
1 | recovery_gate: |
这里的数值不一定通用,但结构上必须完整。
5. 可直接接入服务层的最小恢复决策示例
下面这段 Node.js 示例演示一个最小恢复判定器:
它会区分“继续降级”“可以小流量恢复”“恢复验收通过”。
1 | export function evaluateRecovery(snapshot) { |
再配一个恢复动作策略:
1 | recovery_profiles: |
这样就能避免“指标一恢复就全开”的粗暴切换。
6. 恢复不是一个开关,而是一条放量曲线
很多事故二次爆发,不是因为第一次没止住,而是恢复太快。
更稳的方式是把恢复做成放量曲线:
10%流量恢复- 跑一次关键路径验证
30%流量恢复- 再看一轮 burn-rate / 质量指标 / 副作用
- 最后才恢复到
100%
如果你的系统还涉及工具写操作、自动审批、工作流编排,恢复顺序建议比普通 Web 服务更保守:
- 先恢复只读查询类能力
- 再恢复低风险工具调用
- 最后恢复高风险写操作
因为 LLM 事故里最贵的,往往不是“服务短时不可用”,而是恢复过快后重新触发错误动作。
7. 一周落地建议:先把“恢复完成”写成硬规则
如果你想一周内落地,建议按这个节奏做:
Day 1
为现有事故流程补上状态机:mitigating / degraded / recovering / verifiedDay 2
明确 4 组恢复验收指标和阈值Day 3
接入最小恢复决策器,只控制只读 / fallback / release freezeDay 4
做一次假恢复演练,验证“恢复过快会不会再次触发 burn-rate”Day 5
把恢复证据自动写入 incident 模板,形成复盘输入
先把“什么时候不算恢复”说清楚,通常比继续堆自动化动作更重要。
总结
自动止血解决的是先别继续出血,恢复验收解决的是别把假恢复当成真恢复。
如果没有恢复验收门槛,自动化越强,越可能把错误更快地重新放大。
如果这周你只做一件事,我建议优先完成:
给事故 runbook 增加一个 verified recovery 门槛,并要求系统只有在验收通过后才能自动退出降级态。