429 就换模型?你可能正在把一次故障变成三倍账单:AI Gateway 路由、降级与熔断实战
先说结论
收到 429 就立刻换模型,看起来是在做高可用,实际上可能同时制造三件事:把一个短暂拥堵放大成重试风暴,把本来不该离开某个区域的数据送到不合规的备用线路,再让多个已经接单的模型共同计费。正确做法不是取消 fallback,而是把路由拆成三步:先用能力、地域、数据分类和预算做硬过滤,再根据健康度、延迟与成本选路,最后只对明确可恢复的错误做有界重试。 临时限流型 429 和短暂 5xx 可以降级;401、403、余额耗尽、合规拒绝必须停止并暴露根因。本文用一个 Python 标准库、零网络、零凭据的故障实验,实测路由过滤、429 降级、熔断、hedging 成本与审计预算,7 项验收全部通过。

图 1:原创确定性 PNG 封面。文中的 provider、价格、延迟、Token 和错误均为本地合成教学数据,不代表任何真实厂商报价或 SLA。
一、问题背景:fallback 本来是安全网,为什么会变成放大器
在 AI Platform 旗舰架构 里,我把 AI Gateway 放在控制平面:它不只转发 HTTP,而是要理解模型能力、上下文、数据边界、成本和降级资格。问题是很多系统落地时只写了这样一段逻辑:
try primary model
if error:
try fallback A
if error:
try fallback B
代码很短,事故却可能很长。主线路返回 429,应用层重试两次;SDK 自己又重试两次;网关再切两个模型;最外层 Agent 看到超时,还把整轮任务重新执行。每一层都以为自己只做了一次善意补救,乘起来却像几个人同时按电梯按钮:电梯不会来得更快,控制器反而更忙。
更麻烦的是,模型调用并不是普通静态文件请求。候选模型可能不支持工具调用或 JSON Schema;某些数据只能留在指定区域;不同模型的上下文窗口、输入输出单价和内容策略不同;流式输出已经开始后再换模型,还可能让用户收到拼接答案。“这个地址能返回 200”只证明网络能走,不证明这条路适合这次请求。
二、问题表现:一次 429 如何长成六种生产怪病
我见过的错误路由通常不是直接宕机,而是表现成一些很难归因的“怪病”:
- 尾延迟越来越长:每层都重试,用户等到最后才看到失败;监控只记录最终一次调用,看不见前面已经浪费的时间。
- 账单与成功量不成比例:hedging 同时发出两三份请求,只采用最快答案,但其他上游可能已经开始推理或输出。
- 质量悄悄变化:备用模型不支持相同工具、结构化输出或上下文长度,表面成功,实际把严格 JSON 变成一段自然语言。
- 安全边界被绕过:主线路因为合规策略拒绝,网关却把同一内容送给策略不同的备用线路。这不是高可用,而是自动绕过控制。
- 配置错误被隐藏:401 被包装成“全部模型繁忙”,值班同学忙着扩容,真正的失效凭据仍藏在日志深处。
- 雪崩自我延续:故障线路已经过载,新的请求和重试仍持续敲门;健康线路也被 fallback 流量拖垮。
这像暴雨天打车:附近没车时,平台可以扩大搜索范围;但如果乘客证件失效,换一家车队不会让证件突然有效;如果目的地在交通管制区,也不能偷偷让司机绕过检查站。AI Gateway 要做的是“调度 + 分诊 + 账本”,不是盲目轮询电话号码。
三、先划清边界:AI Gateway 不等于 API Gateway
API Gateway 和 AI Gateway 可以部署在相邻层,甚至共享一部分基础设施,但它们回答的问题不同。

图 2:原创图。API Gateway 更像商场大门,检查身份、入口和客流;AI Gateway 更像医院分诊台,还要判断专科能力、病情等级、床位、距离和费用。两层都需要,不能用其中一个冒充另一个。
API Gateway 通常负责:入口认证、URL/协议路由、租户配额、边缘限流、WAF、证书和入口日志。AI Gateway 在此基础上还要处理:
- 模型是否支持工具调用、视觉、音频、JSON Schema 或特定上下文长度;
- 数据分类是否允许进入某个 provider、区域或部署形态;
- 本次请求的 deadline、Token 上限、成本上限和质量等级;
- 错误是临时拥堵、上游故障,还是凭据、余额、合规等终止错误;
- fallback 是否协议兼容,Prompt/工具 schema 版本是否一致;
- 每次尝试用了多少时间和预算,为什么排除其他候选,最后如何向审计解释。
NewAPI 自托管中转站 可以统一模型入口、Token、渠道和用量,是很实用的网关基础;但“有统一入口”不自动等于“有完整路由策略”。生产系统仍需要在它的前后明确请求封套、错误分类、预算、熔断和审计所有权。
四、正确路由的第一步:先做硬过滤,再谈加权评分
很多路由器一上来就计算“哪个模型最便宜、最快”。顺序反了。数据地域、合规、能力和任务类型属于资格条件,不满足就是不能参赛;只有合格候选之间,才比较价格和延迟。

图 3:原创图。医院不会因为牙科今天便宜,就把骨折患者送去牙科;打车平台也不会因为另一座城市车辆更多,就派一辆根本到不了的车。硬约束先于偏好评分。
我建议每次请求先形成一个不可由模型改写的结构化 envelope,至少包含:
{
"request_id": "req-demo-001",
"required_capabilities": ["tools", "json"],
"allowed_regions": ["region-a"],
"data_classification": "restricted",
"input_tokens_estimate": 10000,
"max_output_tokens": 2000,
"deadline_ms": 1200,
"max_cost_usd": 0.05,
"route_policy": "route-policy-v3"
}
这里使用的都是合成值,不含真实租户、主机、地址或凭据。路由器先排除缺能力、地域不符、分类上限不足、最坏成本超过预算的线路;剩余候选再根据滚动健康度、P95 延迟、排队深度、价格和质量评分排序。
本地实验把四条合成线路放进同一个候选池:一条地域不符,一条缺工具能力,一条最坏成本超出请求预算,只有 route-fit 同时满足全部条件。

图 4:真实本地 stdout 截图。实验没有访问网络;选择结果不是“第一个能连上的”,而是能力、地域、数据分类和成本预算共同过滤后的结果。
能力路由:模型名不是能力声明
不要在业务代码里写“某模型一定支持 tools”。能力应该是版本化注册信息,并经过最小探测与契约测试。工具调用、严格 JSON、多模态输入、最大上下文、最大输出、流式事件格式都可能随 provider、模型版本和兼容层变化。
地域与数据分类:最短路径不一定合法
先把数据分成 public、internal、restricted 等等级,再给每条路由声明允许的等级和区域。restricted 请求不能因为主线路拥堵就自动跑到不允许的区域;合规拒绝也不能通过 fallback 洗成“成功”。这就像学校规定学生档案只能由档案室保管,教室拥挤并不是把档案搬到校外便利店的理由。
成本路由:比较最坏情况,不只看输入单价
估算至少要包含输入 Token、允许的最大输出、缓存命中规则、图片/音频计费和可能的重试预留。只看“每百万输入 Token 单价”会低估长输出和多模态任务。对 Agent,还要按完成一次业务结果的总成本衡量,而不是单次模型调用的价格。
五、429 不是一种原因:必须同时看状态码和错误子码
RFC 6585 定义 429 为 Too Many Requests,并允许服务端返回 Retry-After。现实中的模型 API 还可能用相同 HTTP 状态承载不同业务原因,例如临时速率限制、组织配额耗尽或余额不足。于是“看见 429 就换模型”会把语义压扁。

图 5:原创图。路由决策需要 HTTP status + provider code + 本地策略。同样是 429,rate_limited 可以进入有界 fallback,insufficient_quota 应停止;不能只用状态码做一个巨大 switch。
建议先把各厂商错误归一化为本地稳定分类,再由策略决定动作:
| 归一化原因 | 常见信号 | 默认动作 | 为什么 |
|---|---|---|---|
| 临时限流 | 429 + rate_limited,可参考 Retry-After |
有界退避或兼容线路 fallback | 资源可能很快恢复 |
| 短暂上游故障 | 500/502/503/504、连接超时 | 有界 fallback,计入熔断 | 不是请求本身错误 |
| 认证失败 | 401、invalid_auth |
立即停止、告警 | 自动换路会隐藏凭据故障 |
| 权限失败 | 403、permission_denied |
立即停止 | 不能用备用线路绕过授权 |
| 余额/组织配额耗尽 | insufficient_quota、balance_exhausted |
立即停止 | 这是预算事实,不是短暂拥堵 |
| 合规/数据地域拒绝 | compliance_denied 等 |
立即停止并审计 | fallback 可能构成策略绕过 |
| 参数/上下文错误 | 400、schema/context 错误 | 修正请求,不重试 | 同一坏请求换线路仍然坏 |
“立即停止”指不做自动 provider fallback,不是把错误吞掉。网关应该返回明确、脱敏、可操作的错误类别,同时触发控制面修复。若组织确实希望在某个 provider 余额耗尽时转移预算,应该提前写成一条经过审批、带总预算的显式策略,而不是把它伪装成普通 429 重试。
六、有界重试:不是“重试三次”,而是同时守住四本账
只设置 max_retries=2 还不够。一条可靠请求至少要有四个相互约束的预算:
- 尝试次数预算:整个调用链总共允许几次,而不是每一层各允许几次。
- 时间预算:每次尝试、退避和 fallback 都从同一个 deadline 扣除。
- Token/成本预算:失败前已经生成的内容也可能产生用量;下一条线路必须先估算再保留预算。
- 并发预算:限制同一租户、任务和上游的并发,避免 hedging 与重试一起膨胀。
退避应包含 jitter,避免成千上万客户端在整点同时醒来。Retry-After 是重要信号,但仍要受本地 deadline 和预算约束;上游让你等 30 秒,而用户只剩 800 毫秒,正确结果是尽快失败或走合格备用线路,不是让请求在后台失踪。
实验中,主线路 80ms 后返回合成 429 rate_limited,网关执行 100ms 确定性退避,备用线路 450ms 完成,总耗时 630ms,仍在 1200ms deadline 内;第三次尝试被统一预算挡住。

图 6:真实本地 stdout 截图。两次尝试、总成本和剩余时间被放在同一条证据链里;outbound_network_calls=0 说明所有 provider 都是本地合成对象。
相反,实验给主线路依次注入 401、余额耗尽型 429 和合规型 403,三种错误全部被归类为 STOP,备用线路调用次数保持为 0。

图 7:真实本地 stdout 截图。“服务更可用”不能以隐藏身份、预算或合规根因为代价;这三类错误应进入告警和修复流程。
七、熔断器:保护的是整条线路,不是某一个请求
重试预算回答“这一个请求还能试几次”;熔断器回答“大家是否应该暂时别再敲这扇坏门”。没有熔断,成千上万请求会各自礼貌地重试,把一个局部故障变成全平台排队。

图 8:原创图。家里电路短路后,空气开关先断开;它不会让每件电器继续试十次。冷却后只做一次小探测,确认安全再恢复全部流量。
生产熔断器应注意几个边界:
- 按 provider + 模型/部署 + 区域的故障域统计,不要一个模型坏了就熔断全世界;
- 只把短暂上游失败、超时和慢调用计入健康窗口,用户参数错误不应污染线路健康;
- 401/403 等配置或权限错误应把该路由标记为不可用并告警,而不是反复半开探测;
- 设置最小请求量,避免“刚好失败一次”就打开;使用滚动窗口而不是永久累计;
- OPEN 时快速失败或走合格备用线路,不能继续偷偷探测;
- HALF_OPEN 只允许极少量探针,成功关闭,失败重新打开;
- 熔断状态变化要进入指标和审计,但不要把凭据 ID 写进公开标签。
本地实验让同一线路连续三次返回 503,第三次后进入 OPEN;第 4 个请求零上游调用地快速失败。冷却时间没到仍保持 OPEN,到点后只放行一次 HALF_OPEN 探针,探针成功才回到 CLOSED。

图 9:真实本地 stdout 截图。实验使用虚拟时钟,所以不用真的等待数秒;状态转换是确定性的,特别适合放进 CI 发布闸门。
八、Hedging:可以降低尾延迟,也能让一份答案收到三张账单
Hedging 不是失败后重试,而是第一份请求还没完成时,延迟一小段时间再并发发出相同请求,采用最先返回的答案。它对幂等、只读、尾延迟很长的调用可能有效,但风险也最容易被“平均延迟下降”掩盖。
实验构造了一个故意悲观的场景:A 在 0ms 接单,B 在 200ms 接单,C 在 400ms 接单;B 最早在 700ms 完成,于是网关采用 B 的答案并取消另外两条。但三条线路都已经接受任务,每条合成成本为 0.036 美元,总成本从 0.036 变成 0.108,正好 3 倍。

图 10:真实本地 stdout 截图。这是用来验证预算护栏的合成最坏案例,不声称每家 provider 都会以相同方式计费。取消到达时,上游可能尚未工作、已做部分工作或已完成,真实账单要以厂商规则和用量回执为准。
如果确实要用 hedging,我会设置这些门槛:只允许无副作用的模型推理;默认最多两路;超过历史 P95/P99 的动态阈值才发第二路;发出前先保留最坏成本;首个有效答案胜出后立即取消;把 loser 的 Token、时间和费用单独计量;一旦进入工具调用阶段绝不复制执行。流式响应还要更谨慎——第一段内容已经展示给用户后,不能悄悄换成另一模型继续拼接。
九、预算不是报表:它必须在调用前挡住请求
很多平台“有成本看板”,但账单发生后才展示曲线。那是后视镜,不是刹车。真正的预算控制应采用先预留、后结算:根据输入估算、最大输出和价格表先保留额度;调用完成后按实际用量结算并释放差额;失败或 fallback 前重新计算整条请求的累计最坏成本。
预算至少分四层:单次模型尝试、整次请求、完整 Agent 任务、租户/团队时间窗口。前两层防止一次异常,后两层防止慢性失控。预算耗尽应该返回明确的 BUDGET_EXCEEDED,不应伪装成模型拥堵。

图 11:原创图。路线小票像出租车行程单:要写清为什么派这辆车、绕了哪条路、花了多少;不需要把乘客的银行卡密码和整段私人谈话印上去。
实验里,主线路在合成 503 前已经产生 0.020 美元部分费用,备用线路最坏估算 0.042 美元,两者累计 0.062,超过请求上限 0.050,因此 fallback 在调用前被拒绝。

图 12:真实本地 stdout 截图。审计保留 request ID、策略版本、候选、排除原因、尝试和合成成本;凭据脱敏,原始 Prompt 不入这份路由日志。
这也解释了为什么我在 AI 隐形账单 里强调“每个成功结果成本”:压低单价不等于总成本下降。上下文过长时可以参考 Headroom + NewAPI Token 压缩实战,但压缩、路由、重试和 hedging 的节省/浪费必须进入同一本任务账。
十、可观测性与审计:回答“为什么走这条路”
一次可解释的路由决定至少要记录:
- request/trace ID、租户的不可逆脱敏标识、数据分类;
- 路由策略与价格表版本、所需能力、deadline 和预算;
- 候选集,以及每个候选被排除的稳定原因码;
- 每次尝试的 provider/模型别名、状态、归一化错误、退避和耗时;
- 输入/输出 Token、缓存用量、估算与实际成本;
- fallback、熔断、hedging 和取消事件;
- 最终业务结果,而不只是最后一个 HTTP 200。
不要默认记录完整 Prompt、响应、API Key 或授权头。排障真正需要的通常是结构化元数据、内容哈希、采样后的脱敏片段和可受控访问的证据。OpenTelemetry 的 GenAI semantic conventions 可以作为 span/metric 命名参考,但仍在演进,生产使用应固定版本并建立自己的低基数属性规范。
我会重点监控:fallback 率、终止错误率、每路 P50/P95/P99、熔断打开时长、半开探测结果、hedge winner/loser Token、取消后用量、每个成功任务成本、预算拒绝数和“不合规候选被正确排除”的数量。正确拒绝是安全成功,不能简单算成可用性失败。
十一、零网络故障实验:7 个 PASS 到底证明了什么
本文提供的 Python 标准库实验 不导入任何厂商 SDK,不读取环境凭据,不调用真实模型。脚本把 socket.socket 与 socket.create_connection 替换为 fail-closed guard,若未来误加出站调用会直接报错;当前全部场景的 outbound_attempts 为 0。
它验证六类机制和一条总安全条件:
- 能力、地域、数据分类和预算硬过滤;
- 限流型 429 在次数、时间与成本预算内降级;
- 401、403、余额耗尽与合规拒绝不触发 fallback;
- 连续 503 打开熔断,冷却后由半开探针恢复;
- hedging 的未采用线路也必须进入成本风险统计;
- 累计最坏成本超限时在调用前挡住 fallback;
- 整个实验零真实凭据、零出站网络。

图 13:真实本地 stdout 截图。7/7 PASS 证明的是控制逻辑按预期工作,不证明任何真实 provider 的质量、价格、吞吐或 SLA。
结构化结果会写入 events.jsonl 与 summary.json。所有 provider 名、价格、延迟、Token 和响应均为合成数据,适合教学、回归和 CI,不适合拿来做厂商排行榜。
十二、三平台一键运行:Windows 11、Ubuntu 26.04、macOS 26
完整说明见 README。三个启动脚本只依赖系统中的 Python 3,不需要 Docker、数据库或第三方服务。
Windows 11
下载 PowerShell 一键脚本 与同目录实验文件,然后执行:
powershell -ExecutionPolicy Bypass -File .\run-windows11.ps1
脚本优先使用 py -3,找不到时尝试 python;最后读取 summary.json,只有 7/7 且出站尝试为 0 才返回成功。
Ubuntu 26.04
bash run-ubuntu-2604.sh
对应的 Ubuntu 一键脚本 使用 set -euo pipefail,执行后再次用标准库解析验收结果。
macOS 26
bash run-macos-26.sh
macOS 一键脚本 与 Ubuntu 版本保持相同验收语义,方便比较不同平台输出。本文素材生成时已在本地 macOS Python 环境实际执行通过。
人工逐项执行
如果不想直接跑全部场景,可以人工逐个观察:
python3 ai_gateway_fault_lab.py --scenario routing
python3 ai_gateway_fault_lab.py --scenario bounded-429
python3 ai_gateway_fault_lab.py --scenario terminal-errors
python3 ai_gateway_fault_lab.py --scenario circuit
python3 ai_gateway_fault_lab.py --scenario hedging
python3 ai_gateway_fault_lab.py --scenario budget-audit
Windows 把 python3 换成 py -3 即可。这里所谓“一键”只运行安全的本地模拟,不会发现、修改或调用你的真实网关。
十三、Agent 自动配置方法:让 Agent 执行,但不让它弱化验收
我额外提供了一份可直接下载的 AGENT_TASK.md。把实验目录交给本地 Agent,并给出下面的任务即可:
请只在当前 AI Gateway fault lab 目录内工作:
1. 阅读 README、AGENT_TASK.md 和 Python 实验;
2. 根据 Windows 11 / Ubuntu 26.04 / macOS 26 选择唯一对应脚本;
3. 不添加任何真实 endpoint、主机名、API Key 或网络访问;
4. 执行脚本并解析 lab-output/summary.json;
5. 只有 acceptance.passed=7 且 outbound_attempts=0 才报告成功;
6. 逐项报告失败和 stderr,不得通过删除断言、扩大预算或跳过场景来“修复”。
这与人工执行的区别不是“Agent 有更大权限”,而是它会自动选择脚本、读取结构化结果并整理报告。自动化不能拥有修改验收标准的自由。 如果要把策略迁入真实网关,应另开变更单:先导出当前配置、脱敏备份、生成差异、人工批准,再做 shadow/canary;本文的零网络实验不会也不应该自动碰生产环境。
十四、上线前故障注入:我会把哪些结果写进发布闸门
真实 AI Gateway 上线前,至少要在隔离环境注入这些场景:
- 主线路 429 +
Retry-After,确认总尝试次数、deadline 和 jitter 生效; - 429 + 余额耗尽子码,确认不会自动换路;
- 401、403、合规拒绝,确认错误不被包装成“繁忙”;
- 主线路连续 5xx,确认熔断按窗口打开,OPEN 期间上游调用为 0;
- 半开探针失败和成功各一次,确认流量不会瞬间全开;
- fallback 缺 tools/JSON 能力,确认即使健康也不会入选;
- restricted 数据只有不合规备用线路,确认宁可明确失败也不越界;
- 主调用已有部分 Token,用量加备用最坏估算超预算,确认调用前拒绝;
- hedging loser 在取消前后分别返回,确认用量与浪费可见;
- 流式输出已开始后主线路断开,确认不会拼接两份相互矛盾的答案。
验收指标不是“最终能返回一句话”,而是:重试总次数有上限、重复并发有上限、数据不越界、终止错误不隐藏、熔断能止血、每分钱能归因、每个选择能解释。
十五、落到现有系统:NewAPI、Headroom 与 AI Platform 怎么分工
如果已经运行 NewAPI,可以让它继续承担统一入口、渠道、Token、模型映射、额度和用量;在接入层或其相邻控制模块补齐 request envelope、规范化错误、全链路 retry budget、熔断和决策审计。不要同时在客户端 SDK、Agent 框架和 NewAPI 各开一套独立重试;应选择一个拥有全局 deadline 与成本视角的层做重试所有者,其他层关闭或收窄自动重试。
Headroom 解决的是长上下文压缩,不是错误分类或熔断。它像仓库门口的真空打包台;AI Gateway 是调度中心。压缩后重新估算 Token 可以改善预算,但不能把 Anthropic 原生协议、OpenAI 兼容协议和工具 schema 不加验证地混到同一 fallback 池。具体迁移边界可参考前面的 Headroom 实战。
在更完整的 AI Platform 中,Turn Manager 提供 deadline 与取消树,AI Gateway 负责模型路由、错误分类和成本,Policy Engine 负责数据/合规资格,Worker 负责工具副作用。模型 fallback 不能复制 Worker 工具执行;这也是“推理重试”和“业务重试”必须分开的原因。整个系列的上下文可从 AI Platform 架构阅读地图 进入。
十六、Q&A
Q1:所有 429 都可以换模型吗?
不可以。至少要查看 provider 的错误子码、Retry-After、请求预算和本地政策。临时 rate_limited 可以有界退避/降级;余额或组织配额耗尽应默认停止。只看 HTTP 429 会把两种完全不同的事实混在一起。
Q2:为什么 401 不直接换一条带独立凭据的线路?
因为自动换路会让凭据轮换错误长期潜伏,还可能把本应使用指定身份的数据送到别处。默认停止并修复控制面更可审计。如果业务明确允许独立身份池容灾,必须写成显式、审批过、带数据与预算约束的策略,而不是通用 if error。
Q3:重试几次最合适?
没有统一数字。根据总 deadline、请求到达率、上游容量、失败持续时间和成本决定。交互请求通常宁可少而快;离线任务可以更久,但也要共享总预算。比具体次数更重要的是:只允许一个层拥有重试,使用指数退避 + jitter,并把每次尝试记进同一 trace。
Q4:熔断打开后是不是所有请求都失败?
对被熔断的线路应快速失败;如果存在经过硬过滤的兼容备用线路,可以在总预算内降级。没有合格线路时,明确失败比发送到不兼容/不合规模型更正确。
Q5:什么时候值得用 hedging?
只读、幂等、尾延迟昂贵、输出较短、候选协议和质量相近,并且预算愿意支付重复调用时。不要 hedge 工具副作用;不要在没有 loser 用量指标时上线;不要把三路并发当默认值。
Q6:取消 loser 就不会计费了吗?
不能这样保证。取消是尽力而为:上游收到前可能已经开始或完成计算,不同 provider 的计费规则也不同。按最坏成本预留,按真实 usage 回执结算,并持续测量取消后的浪费。
Q7:AI Gateway 一定要单独做成微服务吗?
不一定。早期可以是模块化单体中的明确模块。关键是它拥有统一错误分类、预算和路由证据,不是进程数量。只有扩缩、权限、团队或故障域真的不同,才值得拆服务。
Q8:只用 NewAPI 的重试和渠道优先级够不够?
自用轻量场景可能够;涉及 restricted 数据、跨区域、多协议工具调用和严格预算时,还要验证它当前版本的错误分类、路由粒度、熔断、全链路 deadline 与审计是否覆盖需求。不要根据产品名称猜能力,要用故障注入证明。
Q9:本实验为什么不调用真实模型?
因为它验证的是控制逻辑。真实 API 会引入网络、凭据、价格变化和不可重复延迟,反而让状态机测试不稳定。先用确定性零网络实验证明边界,再在隔离环境做 provider 合同测试和 canary,两类证据互补。
Q10:最先落地哪三项?
统一错误分类、贯穿全链路的 retry/deadline budget、可解释的 route decision log。它们先回答“能不能重试、还能花多少、为什么走这条路”,然后再加熔断、hedging 和高级评分。
十七、参考资料与最终底线
- RFC 6585:HTTP 429 Too Many Requests
- AWS Builders’ Library:Timeouts, retries, and backoff with jitter
- Microsoft Azure Architecture Center:Retry pattern
- Microsoft Azure Architecture Center:Circuit Breaker pattern
- OpenTelemetry:Generative AI metrics semantic conventions
这篇文章不是反对 fallback。恰恰相反,我希望 fallback 真正成为安全网,而不是一块盖住根因的毯子。最终底线可以压缩成一句话:先判断这条路有没有资格,再判断值不值得走;只为可恢复错误重试,只在总时间与总成本内重试;身份、余额和合规说“停”时,任何备用模型都无权替它们说“继续”。