Fallback 机制指主调用失败后,系统按预设顺序自动切换到备用方案继续完成请求,用户感知不到底层故障。在我们自研的企业级 AI 网关里,Fallback 是一条有序的回退链:请求先打主模型,遇限流、超时、5xx 或模型不可用时,按链顺序尝试下一个备用模型,全部失败才返回错误。网关的降级组件同时负责给内部 AI 爆款文章创作器兜底,创作器的多阶段生成里任何一次模型调用失败,都会自动降级到同能力档位的备用模型,而不是让整篇文章生成中断。单点依赖一家模型是线上事故的头号来源,Fallback 是网关层必须内置的默认能力。
一、Fallback 要处理的故障类型
不是所有异常都值得触发回退,触发条件必须精确圈定。可回退的故障有一个共性:重试或换路能解决。
| 触发类型 | 典型表现 | 处理方式 |
|---|---|---|
| 限流 | HTTP 429 | 切到备用模型或等待退避 |
| 服务端故障 | 5xx、网关超时 | 直接切备用模型 |
| 响应超时 | 超过设定时限无首 token | 取消并切换 |
| 上下文超限 | 输入超过模型窗口 | 切到更大窗口模型 |
| 模型不可用 | 维护下线、欠费停服 | 按链切换 |
客户端 4xx(非 429)不触发回退,那是请求本身写错了,换模型照样失败。内容审核拒绝同样不回退,否则会把问题请求在多个模型间反复放大,白白烧钱。
二、回退链的实现
2.1 配置驱动的有序回退链
每条链路在配置中心声明,顺序即优先级。网关按序调用,命中成功即返回,并把实际生效的模型名回传给调用方,方便对账。
fallback:
chains:
article-generate: # 创作器成文阶段
- provider: openai
model: gpt-4o
- provider: anthropic
model: claude-sonnet
- provider: qwen
model: qwen-max
2.2 回退执行器
执行器按链逐个尝试,每个环节都带上超时控制,防止慢模型拖死整条链:
public ChatResult callWithFallback(Chain chain, ChatRequest req) {
List<ModelEndpoint> endpoints = chain.endpoints();
for (int i = 0; i < endpoints.size(); i++) {
ModelEndpoint ep = endpoints.get(i);
try {
return adapterRegistry.get(ep.provider())
.chat(req.withTimeout(ep.timeout()));
} catch (RateLimitException | TimeoutException | ServerErrorException e) {
log.warn("endpoint[{}] failed: {}, switch to next", ep.name(), e.getMessage());
metrics.recordFallback(chain.name(), ep.name(), i + 1);
continue;
}
}
throw new AllEndpointsFailedException(chain.name());
}
失败现场全部记录,包括错误类型、失败位置、切换耗时,落到监控面板上。回退频繁的链路会被标记告警,提示运营检查主模型健康度或调整链顺序。
三、流式场景下 Fallback 的特殊处理
SSE 流式输出给 Fallback 加了约束:一旦首 token 已推给前端,连接就进入发送态,此时不能切换模型,否则会输出两段不一致的内容。网关的降级策略因此按阶段切分:
- 请求建立阶段:连接尚未写入任何数据,主模型报错可安全切到备用模型,前端无感知;
- 流式传输阶段:已产生输出流,不做模型切换,改为提前结束并给前端推送结束标记;
- 中断恢复阶段:连接意外断开时,网关根据断点位置决定重试还是降级为同步补发。
创作器把这条规则用在多阶段生成上:选题、大纲、成文、润色四个阶段各自独立调用模型,单阶段失败只重跑该阶段,不会污染已生成的阶段结果。
四、回退模式怎么选
| 回退模式 | 示例 | 适用场景 |
|---|---|---|
| 同档位跨厂商 | gpt-4o → claude-sonnet | 对质量要求严格,不可降质 |
| 降级换成本 | 重型模型 → 轻量模型 | 保服务在线优先于推理深度 |
| 跨区域冗余 | OpenAI 直连 → Azure OpenAI | 区域性故障规避,保持同厂商生态 |
生产环境建议 2-3 个回退目标,太少兜不住故障面,太多会放大成本和延迟。回退目标优先选能力相近的模型,避免输出质量断崖式下降;同时保证跨厂商,同一家厂商多个模型同时故障时,同厂商回退等于没回退。
五、Fallback 与健康检查、路由的协同
Fallback 不能孤立设计,它和网关的健康检查、智能路由是同一套容错体系的三层。健康检查负责定期探活,把持续异常的模型从路由候选里摘除;智能路由负责在健康集合里选最优模型;Fallback 负责兜住探活周期内的突发故障。三者的时序关系是:路由先选主模型 → 调用失败 → Fallback 按链回退 → 连续失败上报健康中心 → 健康中心把该模型隔离 → 后续请求直接绕开。这样每层各管一段,故障处理从单次请求的微观兜底,升级到分钟级的全局收敛。
协同落地的关键是把失败数据打通。Fallback 执行器每触发一次切换,就向健康中心写一条带错误类型的记录,健康中心按模型聚合失败率。当某个模型在短时间内回退次数超过阈值,健康中心主动降低它的路由权重,而不是等探活周期结束。这也解释了为什么回退要精确区分可回退与不可回退异常——错误类型直接决定健康中心的判定逻辑,统计口径不干净,隔离决策就会失真。
六、Fallback 设计的三个坑
回退链里不能有死循环,链内模型互相回退会形成环。回退次数要限流,所有模型同时限流时,疯狂重试只会加剧雪崩,应退避后快速失败。还有一个容易被忽略的点:回退要带预算约束,备用模型可能更贵,超预算时宁可返回明确的失败,也不要默默烧钱。
常见问题(FAQ)
Q1:Fallback 和重试有什么区别?
重试是同一目标再试一次,Fallback 是换目标继续。网关里两者组合,先重试再回退。
Q2:回退后输出质量下降怎么办?
回退目标选同档位模型控制质量差,且回退时给前端标记模型名,方便业务侧提示。
Q3:什么时候该触发回退而不是直接报错?
限流、超时、服务端故障这类可恢复问题触发回退;客户端参数错误直接报错,不回退。