线上出问题怎么查?一套可复现的排障 SOP(O04)

35 阅读5分钟

线上出问题怎么查?一套可复现的排障 SOP(O04)

系列《AI 应用生产化手册》第 9 篇(共 30 篇)|配套开源项目:github.com/ChenYingbo/… 本篇是模块二(可观测性)收尾:日志 → 追踪 → 指标 → 排障,四件套齐了

一、先看问题:工具是散的,人是慌的

前三篇备齐了观测工具(日志/trace/指标),但还差最后一块拼图:

  1. 工具是散的——出问题时手忙脚乱:先看哪个?指标、trace、日志怎么串起来?
  2. 靠经验不靠流程——老手凭直觉定位,新手抓瞎;同样的故障每次排查路径都不一样。
  3. 修完就完事——没有复盘,同类故障下周再来一遍。

解法:把排查过程固化成 SOP + 工具化(一键收集现场)+ 复盘模板。

核心认知:可观测的终点不是工具,是"流程"——让任何人(包括三个月后的你)拿到 SOP 都能按步骤定位问题,并且每次排查都在积累案例库。

二、原理:五步排查路径

① 指标发现(O03)  "整体不对劲" → 定级、定影响面
        ↓
② trace 定位(O02) "找到具体请求" → 看哪一步异常
        ↓
③ 日志看细节(O01) "补证据" → 错误详情、上下文
        ↓
④ 复现 + 修复 + 回归(E04 门禁)→ "修好 = 评测通过"
        ↓
⑤ 复盘归档 → 防复发行动项

为什么是这个顺序? 指标最快但最粗(只知道"坏了");trace 精确但要知道看哪条;日志最细但要先有 request_id。从粗到细,每步都在缩小范围。

常见故障分类(先分类再排查)

故障第一嫌疑定位入口
幻觉/答错上下文问题trace 的 input + 评测
超时模型/网关慢metrics 分位 + trace span 耗时
错误率上升网关/Key/429现场快照的错误列表 + trace
上下文溢出长对话管理trace 的 input tokens
成本爆炸重试风暴/死循环metrics 成本 + token 峰值
工具错配工具 Schema/路由trace 的 tool span(RAG/Agent 后)

分类的价值:第一眼决定去哪一层看,而不是漫无目的地翻。

关键纪律:先止血,再根治

S1 故障(全挂/数据泄露):
  ① 先降级/回滚 → 恢复服务
  ② 稳定后再慢慢查根因
  ③ 严禁边排查边让用户继续踩雷

排障的第一优先级永远是"恢复服务",不是"找到原因"。

复盘三问(没有行动项 = 没复盘)

  1. 根因是什么?(一句话,不是"网络波动"这种废话)
  2. 防复发措施是什么?(代码/告警/评测集三选一,必须落地)
  3. 案例库是否补了一页?(下次同类问题 10 分钟解决而不是 2 小时)

三、动手:一键收集现场快照

git clone https://github.com/ChenYingbo/ai-prod-demo.git && cd ai-prod-demo
source .venv/bin/activate

# 收集现场(用样例日志演示,免 Key)
python scripts/diagnose.py --log tests/fixtures/sample_structured.log --slow-ms 2500

真实输出:

===== 现场快照 =====
[WARN] app /health: 连接被拒
[WARN] LiteLLM 网关: 连接被拒
[OK ] Langfuse: HTTP 200
[INFO] 日志行数: 33
[INFO] 近期事件: chat_request(r10), llm_call(r10), chat_error(r10)
[INFO] 错误数: 1(最近: 1 条可见)
  ERROR r10: LLM 调用失败: Error code: 502
[INFO] 慢请求(>阈值ms): 1 条
  SLOW r05: latency=3000ms
[INFO] token 峰值: in=180 (request r09)

一条命令同时回答四件事:服务健康吗?最近有哪些错误?哪些请求慢?谁在烧 token?

三个故障演练(建议有 API Key 后做)

故障制造方法定位路径
改坏提示词把 prompts/chat-system/ 模板改成"只会说不知道"评测通过率暴跌 → trace 看 input → 定位提示词
网关故障docker stop ai-prod-litellm现场快照网关 WARN → 错误率飙升 → 修复 = 重启 + 补 fallback
模拟超时.env 设 LLM_CONNECT_TIMEOUT=0.5metrics P95 暴涨 → trace 看 llm_call 超时 → 修复 = 合理超时 + 重试

每个故障走完整 SOP:收集现场 → 指标定级 → trace 定位 → 修复 → 回归门禁 → 归档案例。

案例库归档

docs/cases/CASE-2026-001-提示词退化.md
docs/cases/CASE-2026-002-网关宕机.md
docs/cases/CASE-2026-003-超时风暴.md

四、真实踩坑

  1. 跳过收集现场直接猜:现场没了(日志轮转)就只能猜——先跑诊断脚本
  2. 先找根因再止血:S1 必须先降级/回滚,让用户继续踩雷不可接受
  3. 只修表面:502 重启网关就好了,但根因(无 fallback)没解决——下月再来
  4. 修好不回归:改完直接上线,没跑门禁——"修 A 坏 B"就是这么来的
  5. 复盘没有行动项:写"加强监控" = 没有复盘
  6. (实测)故障期的错误会被缓存:我们真实踩过——兜底答案被 SQLite 缓存,故障恢复后重复提问仍命中"服务不可用"。排障时记得清缓存,否则你会以为故障没好
  7. 三样工具数据脱节:request_id 没贯穿 → 指标、trace、日志对不上——request_id 是这一切的前提

五、模块二小结(可观测性 4 篇收官)

篇解决的问题核心交付
O01出事了不知道发生了什么结构化日志 + request_id
O02看日志像脑内拼图Langfuse 可视化 trace
O03不知道整体表现指标分位 + 告警
O04排查靠经验排障 SOP + 现场快照工具 + 复盘模板

一条主线:从"出事了才知道"到"随时知道在发生什么、按流程定位到根因"。