模型挂了全站 502?降级链让它先保住“有响应”(R04)

系列《AI 应用生产化手册》第 13 篇(共 30 篇)|配套开源项目:github.com/ChenYingbo/... 本篇是模块三(上线治理)收尾:提示词版本 → 灰度 → A/B → 回滚降级,四件套齐了

一、先看问题:出事了怎么办

灰度、A/B 都就位了,但"出事了怎么办"还是老三样:

  1. 主力模型挂了 = 用户全挂------网关或主力模型故障,所有请求 502,只能干等恢复。
  2. 回滚 = 重启发版------改坏想回退,要重新部署旧版本,几分钟到几十分钟。
  3. 没有开关------有些功能想"立刻关掉",但没有开关,只能改代码。

解法:降级链(主力→备用→规则兜底)+ 功能开关------模型挂了自动切备用,全挂了给规则兜底,功能可一键开关。

核心认知:恢复能力 = 上线能力。没有"1 分钟止血"手段的上线,是裸奔上线。降级不是"质量变差",是"在故障期保住基本可用"。

二、原理

降级链设计(主力 → 备用 → 规则兜底)

objectivec 复制代码
主力模型(chat-strong)
   │ 失败
   ▼
备用模型(chat-cheap)    ← 便宜模型顶上,功能可用但质量略降
   │ 失败
   ▼
规则兜底(rule-fallback) ← 固定话术,保住"有响应"而非 502
级 保住什么 代价
主力 完整质量 贵
备用 基本功能 质量略降、成本低
规则 "有响应"(不 502) 无智能,需向用户明示降级

三原则 :① 备用模型要定期验证 (没验证过的备用 = 心理安慰);② 降级必须可观测 (degraded 标记 + 日志);③ 规则兜底是最后防线,不能当常规路径。

功能开关(Feature Flag)

ini 复制代码
FEATURE_BACKUP_MODEL=1   开/关备用模型降级
FEATURE_RULE_FALLBACK=1  开/关规则兜底
CANARY_ROLLOUT=10        灰度放量(R02)

开关设计要点:走配置不走代码(改开关不用发版);每开一个功能先想"怎么关掉它";开关状态要可观测。

止血三件套

手段 时机 效果 成本
重试 瞬时故障(网络抖动) 自动恢复 低
降级 持续性故障(模型挂了) 保住基本可用 低(切备用)
回滚 变更导致的故障(改坏了) 回到上一稳定版本 中(重部署/切版本)

决策顺序:先重试(自动)→ 再降级(配置)→ 最后回滚(发版)。能配置解决的别发版。

回滚决策流程

复制代码
告警/用户反馈
  ↓ 分级:S1 全挂/数据泄露?
  ↓ 立即止血(降级链自动生效 + 手动关开关)
  ↓ 判断根因:变更 or 外部故障
  ↓ 变更 → 回滚(提示词版本/放量归零/切备用)
  ↓ 外部 → 降级链等恢复 + 通知供应商
  ↓ 恢复后 → 复盘归档

三、动手:验证降级链三种路径

bash 复制代码
git clone https://github.com/ChenYingbo/ai-prod-demo.git && cd ai-prod-demo
source .venv/bin/activate

# 1. 单元验证(fake client,无网络)
pytest tests/test_fallback.py -q
# 6 个用例:主力成功 / 主力失败备用成功 / 全挂规则兜底 / 规则关闭抛错 / 备用关闭直落规则

# 2. 真实演练:网关停掉,请求应自动降级
LLM_BACKUP_MODEL=chat-cheap uvicorn app.main:app --port 8000
# 另开终端(网关已停):
curl -X POST http://localhost:8000/api/chat -H "Content-Type: application/json" \
  -d '{"question":"什么是 RAG?"}'

真实返回(没有降级链之前这里是 502):

json 复制代码
{"answer":"抱歉,模型服务暂时不可用,请稍后重试。","model":"rule-fallback","degraded":true}

开关演练:让错误"看得见"

bash 复制代码
# 关闭规则兜底 → 全挂时恢复 502
FEATURE_RULE_FALLBACK=0 LLM_BACKUP_MODEL=chat-cheap uvicorn app.main:app --port 8000
curl -X POST http://localhost:8000/api/chat -H "Content-Type: application/json" -d '{"question":"hi"}'
# 预期:502(降级链打穿,错误不再被兜底掩盖)

规则兜底是双刃剑:救用户但也掩盖错误------生产上"全挂 502"本身就是该告警的信号,兜底话术 + 告警要同时配。

降级证据链(真实日志)

ini 复制代码
event=llm_fallback from_model=chat-strong to_model=(next) error="Error code: 502"
event=llm_fallback from_model=chat-cheap to_model=(next) error="Error code: 502"
event=llm_rule_fallback reason="Error code: 502"
event=chat_response latency_ms=3188 degraded=true

按 llm_rule_fallback 计数即可告警"降级风暴"。

快速恢复的补充件(配套项目已实现)

  • drain :scripts/drain.sh 优雅停机注释版(SIGTERM → 等在途请求 → 上限)
  • 停机上限 :uvicorn ... --timeout-graceful-shutdown 30
  • SSE 断线续传 :/api/chat/stream 支持 resume_from / Last-Event-ID------掐断后前端自动重连"接上继续"

四、真实踩坑

  1. 备用模型从不验证:配置了备用但没真实跑过------故障时才发现备用也挂了;定期用评测集跑备用
  2. 规则兜底掩盖错误:全挂也返回 200,告警看不见------兜底 + 计数告警必须同时配
  3. 降级不标记 :degraded 不返回、日志不打------用户和监控都不知道在降级
  4. 开关太多没人管:每开一个功能留一个开关------开关要有 owner 和说明
  5. 降级和熔断混淆:降级是"主动切备用",熔断是"检测故障后自动断流"------先有降级链,再上熔断器
  6. 把降级当常规路径:一直走规则兜底还美其名"降级中"------降级要有告警、要有时限

五、模块三小结(上线治理 4 篇收官)

篇 解决的问题 核心交付
R01 提示词裸奔 提示词即代码(版本/评审/回滚)
R02 全量冒险 灰度分桶 + 放量节奏
R03 感觉 ≠ 结论 A/B + z 检验 + 双维度
R04 出事了怎么办 降级链 + 功能开关 + 止血三件套

一条主线:把"变更"从"赌博"变成"有版本、有灰度、有实验、能止血的工程流程"。

明天(C01):进入模块四《Token 成本模型》------把"花了多少钱"算清楚(含真实 50 次调用 0.001 元/请求的实测)。 收藏 + 关注,每天一篇,30 天把 AI 应用送上生产。

相关推荐
isNotNullX34 分钟前
仓储管理最全框架:6大流程、8项指标、10个管理动作、12个常见问题
大数据·人工智能
小白菜001 小时前
AI的理解
人工智能·机器学习
科技苑1 小时前
C++ CAS与ABA问题详解,无锁编程的经典陷阱怎么解决?
c++·人工智能
DFT计算杂谈2 小时前
可DIY布里渊区图像绘制编辑器
人工智能·机器学习·语言模型·矩阵·编辑器
国科安芯2 小时前
把接口变成观测量:CANFD收发器状态可观测性驱动的星上故障检测隔离与恢复方法
大数据·人工智能·物联网·卫星·抗辐射·通信芯片·载荷
7177772 小时前
企业研发平台选型指南:从代码托管到全流程研发管理的判断框架
人工智能·gitee
泯泷2 小时前
模型越聪明越健忘?“上下文腐烂”背后的 3 个解法
人工智能·llm·agent
甲维斯2 小时前
Fable5.2 画手柄很牛,小测3个例子!
人工智能