商用大模型 API 超时异常:生产环境兜底策略与工程实现
超时异常为何在生产中格外棘手
大模型推理天然比传统 API 慢:一次 GPT-4o 请求在高负载时响应时间可能拉到十几秒,Claude 的长上下文补全更容易触发客户端默认的 30 秒超时。与普通接口不同,大模型请求往往已经消耗了上游算力,客户端超时并不意味着服务端已停止计算,贸然重试会带来重复计费与幂等风险。因此,超时的处理逻辑必须单独设计,不能套用通用 HTTP 重试框架的默认策略。
先把超时分清楚:连接、首字节与总时长
实践中至少要区分三类超时:连接超时(TCP 握手阶段)、首字节超时(TTFB,等待模型开始吐 token)、读取超时(流式传输中相邻两个 chunk 的间隔)。三者应当分别设置阈值,而非共用一个全局值。对于流式输出场景,建议将读取超时设在单个 chunk 间隔上(通常 5~15 秒),而非整条流的总时长,否则长文本回答必然触发误判。
连接超时可以设得相对短(3~5 秒),因为 API 中转站到上游模型的链路通常是预热的长连接,若连接阶段就超时,多半是网络或 DNS 问题,重试意义不大。首字节超时则需要根据模型类型区分:轻量模型可设 10 秒,重型推理模型可放宽到 30~45 秒,并在配置中显式标注,避免后续维护者随手改小。
重试策略:什么情况下才该重试
并非所有超时都适合重试。安全可重试的场景包括:连接超时(未发出请求体)、首字节超时且确认上游返回 408 或 504(说明服务端已中止)、网络层读取中断(TCP RST)。不安全的场景包括:请求已经发出且服务端返回了部分 token(流中断),此时服务端可能仍在写入,重试会产生两份并发请求;以及涉及写操作的 function call(如数据库写入),重试前必须先确认幂等性。
退避策略推荐指数退避加随机抖动(jitter),初始间隔 1 秒,最大间隔不超过 16 秒,最多重试 3 次。重试次数到达上限后应抛出明确的业务异常,而非静默返回空值——空值往往比异常更难排查,会把问题藏到下游业务逻辑里。
降级路由:备用模型的切换时机与选型
超时兜底的核心手段之一是模型降级路由:主路径失败后自动切换到备用模型或更快的小参数模型。典型做法是将请求配置写成优先级列表,例如首选 GPT-4o,首字节超时后降级到 GPT-4o-mini,再次超时后返回缓存的兜底回复或触发人工介入。降级不等于无限重试,每次切换都应计入总超时预算,整条链路的最大等待时间要由业务层统一约束。
选择备用模型时需要注意接口兼容性。OpenAI 兼容的 API 中转站能简化这一过程:同一套请求参数(messages、temperature、max_tokens)对 GPT、Claude、Gemini 均适用,切换只需改 model 字段,无需改动业务逻辑。快米兔 API 的 OpenAI 兼容接口支持在同一端点调用多家模型,这对需要在运行时动态切换备用模型的场景有一定工程价值。
熔断器:防止雪崩的关键一环
单纯的重试策略在上游持续不可用时会放大请求量,加重故障。生产级兜底方案需要加入熔断器(Circuit Breaker)。推荐采用三态模型:关闭(正常放行)、打开(直接返回降级结果,不再请求上游)、半开(定时放入少量探测请求判断上游是否恢复)。熔断阈值通常设置为滑动窗口内超时率超过 50%,持续 10 秒后触发断路。熔断期间的响应可以走本地缓存、静态兜底文案或异步队列,具体取决于业务对实时性的要求。
熔断器的状态应当被监控系统捕获并告警。如果熔断频繁触发却没有告警,说明监控覆盖有盲区,问题会在日志里悄悄累积。建议将熔断事件、重试次数、降级触发次数作为独立指标上报,而不是仅仅依赖错误率和延迟 P99。
超时预算的整体设计
端到端的超时控制需要从调用链顶层开始分配预算。假设用户侧可接受的最大等待是 60 秒,那么业务层、中转层、上游模型各占多少必须提前约定,并通过 context deadline(Go)或 CancellationToken(C#)等机制向下传递,避免上层已经超时、下层仍在等待浪费资源。这一思路在微服务架构中尤为重要,大模型调用往往是某条请求链路中耗时最长的节点,一旦没有向下传递截止时间,整条链路的超时预算就会失控。
快米兔 API 按量计费,不设最低消费,适合在测试阶段反复调整超时参数与降级策略,而不必担心固定费用的浪费。实际上线前,建议用压测工具模拟上游高延迟场景,验证熔断器触发时序与降级路径是否符合预期,而不是等到生产故障时才第一次走到这段代码。具体接入方式可参考 快米兔 API 官网说明。