供应商的稳定性不由你决定,但用户看到的那三十秒由你决定。
一、周日晚上,AI 按钮变成一句英文报错
苏芮一个人做客服回复助手,39 美元一个月,客户是十几个在电商平台开店的小团队。周日晚八点,正是订单咨询最多的时候,供应商的主接口开始返回 503。
以下情境为教学假设,人物、引语和数字不代表经核实的真实案例。
她的代码只写了「调用、等待、显示」。没有超时,没有重试,也没有第二个供应商。前端转圈三十秒后弹出一句英文报错,用户以为是自己网络问题,反复点击,把还在排队的请求又翻了一倍。
更糟的是草稿。用户已经写了三行回复,点「生成」后页面跳转,回来时输入框空了。那一晚她收到 11 封邮件,其中 4 封要求退款。退款金额不大,但她失去的是「这个东西靠得住」的判断。
她第二天做的第一件事不是换供应商。她先把「失败」当成一个必须设计的状态:接口可能慢、可能拒绝、可能中途断开,产品在每种情况下都要有一条能走完的路。降级不是备用方案,而是功能的一部分;用户真正购买的,是供应商不稳定时仍然能把话说完的确定性。
故障不是小概率。 一个人产品没有 on-call、没有多区域、没有谈判来的 SLA,供应商一次例行发布就可能让功能停摆半小时。把故障当作每月必然发生一次的事件来设计,比赌它不发生更便宜。
停机半小时的代价可以估。 那晚她退了 4 单、收到 11 封邮件、花了两小时回复,直接损失不到 160 美元;但如果那十几个客户里有两家在续费时犹豫,损失就变成每月 78 美元。降级预案买的不是可用性数字,是续费时的信任。
二、第一层:同供应商的超时与重试
第一层不换供应商,只解决「等太久」。三个超时分别管住连接、首 token 和总时长,缺一个都会让请求挂死。
| 控制项 | 阈值(教学假设) | 超时后的动作 |
|---|---|---|
| 建立连接 | 3 秒 | 立即取消,进入重试 |
| 首 token | 10 秒 | 中止本次调用,换重试或降级 |
| 总时长 | 30 秒 | 停止等待,返回可恢复错误 |
| 重试 | 最多 2 次,退避 1 秒、3 秒,带 ±30% 抖动 | 仍失败则进入第二层 |
三个超时要分开设。 连接 3 秒管的是网络与 DNS,首 token 10 秒管的是供应商排队,总时长 30 秒管的是用户耐心。只设总超时,会出现「连接成功但一直不吐字」的假健康状态;只设连接超时,则慢响应会把并发占满。
阈值要按 p99 取,不按平均值取。 平均 4 秒的接口,p99 可能是 25 秒;按平均值设 10 秒总超时,会把最慢的那批用户全部变成失败。用最近七天的日志取 p95 与 p99,再决定三个数字,别拍脑袋。
重试必须带抖动。 固定间隔会让所有客户端在同一秒再次涌入,把一次抖动放大成雪崩。退避加随机抖动,能把重试摊平到一个区间;两次仍失败就停手,把请求交给下一层,而不是无限重试。
只对可重试的错误重试。 429、500、502、503、504 和连接超时可以重试;400、401、403、422 重试多少次都一样,只会放大账单。把错误码分类写成一张小表,比在 catch 里统一重试更省事。
重试的成本要算进预算。 一次用户请求最多变成三次计费调用,第 02 篇的每用户成本必须乘上这个系数。若重试率长期高于 5%,说明供应商的尾延迟已经不适合当前场景,该考虑换层而不是继续加退避。
不要把重试藏起来。 如果用户已经等了 20 秒,界面要显示「正在换一条线路」,而不是继续转圈。透明不会让等待变短,但会让用户知道产品还在工作。
三、第二层:第二供应商与弱模型
第二层的目标不是「效果一样好」,而是「还能给出一个可用的结果」。它必须在平时就接好,故障当天才找备用,等于没有备用。
| 触发条件 | 降级目标 | 质量代价 | 用户感知 |
|---|---|---|---|
| 主供应商 5xx 或连续 3 次超时 | 第二供应商的同档模型 | 措辞差异,需重跑评测 | 多等 2 到 5 秒 |
| 第二供应商也失败 | 弱模型 | 完整性下降,需要标注「简版」 | 结果更短 |
| 弱模型仍失败或触发成本熔断 | 模板或缓存 | 只给固定结构,不生成新内容 | 明确标注「模板回复」 |
| 三层都不可用 | 人工队列 | 延迟以小时计 | 进入待处理列表 |
第二供应商要平时就跑。 每周用同一组 50 条用例在两家各跑一次,记录通过率、p95 延迟和单条成本。只写在配置里、从没跑过的备用供应商,故障时大概率因为鉴权、模型名或参数差异直接失败。
提示与解析必须保持中立。 不要把某家的特殊参数、特殊字段或特殊格式写进业务代码;用一层薄适配把请求和响应归一化。这样换供应商是改配置,不是改二十处解析逻辑。
弱模型不是随便挑一个便宜的就上。 它要满足两个条件:能在 30 秒内返回,且在你的 50 条用例上不出现严重错误。完整性可以下降,事实性和安全性不能下降;否则降级只是在制造另一种事故。
模板与缓存要覆盖最高频的五个场景。 退款安抚、物流查询、缺货说明、改地址、发票问题,每个写一段可填空的固定话术;同一个问题在 24 小时内重复出现时,直接返回上次已确认的答案并标注来源。模板不智能,但它能在所有模型都不可用时让用户把话发出去。
降级不能静默。 用户需要知道这封回复是「简版」还是「模板」,也需要一个「重新生成」的入口。静默降级会让用户在不知情的情况下把低质量内容发给自己的客户,那比报错更伤信任。
备用层也要有预算。 第二供应商按同样的单价计费,故障期间流量翻倍,账单也会翻倍。给降级路径单独设日预算,超过就提前进模板,而不是让备用层变成第二个成本黑洞。
四、第三层:熔断、队列与用户可见行为
第三层管的是「别再打了」。当供应商已经明确不可用,继续请求只会拉高延迟、烧掉预算,并让恢复后的第一波流量更难处理。
| 熔断状态 | 判定 | 系统动作 | 用户看到 |
|---|---|---|---|
| 关闭 | 正常 | 放行主供应商 | 正常生成 |
| 打开 | 60 秒内 5 次失败 | 直接走降级,不再请求主供应商 | 稍慢,但不再空转 |
| 半开 | 打开后 30 秒 | 只放 1 个探针请求 | 无感 |
| 队列满 | 待处理超过 50 条或等待超过 15 分钟 | 丢弃低优先级功能,保留核心 | 排队提示与预计时间 |
熔断参数要敢于写死。 60 秒内 5 次失败就打开,30 秒后半开放一个探针,探针成功再关闭。参数不需要调得很精细,关键是有明确的状态机,而不是每个请求都去试一次。
429 要尊重 Retry-After。 供应商明确告诉你多久后再来,就不要按自己的退避硬闯。把 Retry-After 换算成队列的等待时间,超时未恢复就走降级;无视这个头,只会换来更长的封禁。
队列一定要有上限。 无上限的队列会把内存和用户耐心一起耗尽。设 50 条或 15 分钟的上限,满了先丢批量、导出、润色这类低优先级功能,保留用户正在等待的那一条。
用户可见行为要写死五条。 核心工作流不依赖 AI 也能完成;AI 按钮禁用时说明原因与预计恢复时间;草稿自动保存并在恢复后回填;失败页提供重试与人工入口;状态页与产品内提示使用同一句话。
状态页不需要复杂。 一个静态页面加三个状态:正常、降级、故障,写清受影响的功能和更新时间。它的作用不是展示技术,而是让用户不必发邮件问「是不是你们坏了」。
同一句提示要复用。 按钮禁用文案、失败页、状态页、邮件通知使用同一句「AI 生成暂时不可用,预计 XX:XX 恢复,你仍可手动编辑」,避免用户在四个地方看到四种说法。
每月做一次 30 分钟故障演练。 在测试环境注入 timeout、429、500 三种响应,每种跑 20 个请求,记录降级成功率、用户可见失败率和补偿成本。演练不需要真实故障,只需要确认每条路径都还能走通。
演练结果要进复盘表。 哪一层最先触发、哪一层没有生效、用户看到了什么、补了多少钱,四项都写下来。连续两个月同一层失效,说明问题在实现而不是供应商,应该改代码而不是换合同。
五、行动清单与复算验收
先做三件今晚就能上线的事:给请求加三个超时、把重试限制在可重试错误、给 AI 按钮加一个能说明原因的失败态。它们不需要第二家供应商,却能消掉大部分「转圈三十秒然后英文报错」的体验。
然后再接第二层与第三层。第二层至少提前两周准备,因为要跑评测、要适配响应格式;第三层可以先用静态模板和人工邮箱兜底,等量上来再补队列。
- 为连接、首 token、总时长分别设置 3 秒、10 秒、30 秒超时。
- 只对 429、5xx 与连接超时重试,最多两次并加抖动。
- 接一家第二供应商,用同一组 50 条用例每周双跑。
- 准备弱模型与五个高频场景的模板话术,标注「简版」或「模板」。
- 配置 60 秒 5 次失败的熔断与 30 秒半开探针。
- 设置队列上限,写清满了以后丢弃哪些低优先级功能。
- 让 AI 失败页保留草稿,并提供重试、人工入口与状态页链接。
- 每月注入 timeout、429、500 各 20 次,记录三个指标与补偿成本。
验收标准:在供应商完全不可用的 30 分钟内,用户仍能完成核心工作流、看到一句能读懂的原因,并且你能从日志里算出降级成功率和这次故障的补偿成本。
可用性 = 1 − 失败请求 ÷ 总请求 = 1 − 46 ÷ 2000 = 97.7%
降级成功率 = 成功降级请求 ÷ 触发降级请求 = 168 ÷ 180 = 93.3%
三层覆盖率 = 任一层成功请求 ÷ 总请求 = 1954 ÷ 2000 = 97.7%
结论:覆盖率与可用性同值,说明 46 次失败全部落在三层之外;先把失败归类,再决定补第四层还是收窄入口
使用边界与实操验收
本文假设 AI 功能已经上线,且你至少能改自己的超时、重试和前端状态。它不讨论网关实现、跨区域容灾与供应商合同条款;这些超出一个人当前能维护的范围。
- LLM 网关与多模型路由:统一入口、策略分流与故障转移 :它讲网关如何统一入口与策略分流,本文只写一人在应用层能做的三层降级。
- AI 网关与模型路由:多模型统一入口、fallback、限流与成本控制 :它讲 fallback 与限流的工程实现,本文把 fallback 收敛成可演练的预案。
- 模型网关与多模型路由 :它讲多模型路由与熔断配置,本文不搭网关,只定义触发条件与用户可见行为。
实操验收建议挑一个低峰时段做一次真实演练:把主供应商的密钥临时改错,观察产品是否在 60 秒内进入降级、用户是否看到可读提示、草稿是否还在、恢复后是否能继续。整个过程控制在 30 分钟内,结束后把三个指标填进同一张表。
三种情形不适用本文。 一是 AI 是产品唯一价值、没有非 AI 路径可保留;二是企业私有部署,故障沟通由客户管理员负责;三是供应商合同承诺了赔付,降级策略需要与法务口径一致。
关键参考与核验范围
核对日期:2026-10-25。下列来源仅支持明确标注的机制或原则。
- AWS Builders’ Library:Timeouts, retries, and backoff with jitter : 用于核对超时、重试放大与抖动退避的工程取舍。
- Claude:API errors : 用于核对错误响应的厂商示例;不是其他供应商的统一错误契约。
使用边界。 三层预案、2000 次请求与成功率是教学假设,不是供应商 SLA。备用模型与主模型可能同时计费,不能假设超时就未计费。
如何自行复核。 在总截止时间内模拟超时、429、503与备用失败,检查实际返回、预算消耗和用户提示;缓存必须按租户、权限及有效期隔离。
系列导航
- 上一篇:滥用防线:输入过滤、输出约束、速率与审计
- 下一篇:把推理成本写进价格:额度、超额与升级触发
- 回到目录:一个人给产品加 AI:判据、成本、护栏与验收
- 相关阅读:LLM 成本治理与 Token 优化 、滥用防线:输入过滤、输出约束、速率与审计
继续阅读
探索更多技术文章
浏览归档,发现更多关于系统设计、工具链和工程实践的内容。