免费LLM API返回429怎么办?实战排查与多源调度手册

把免费 LLM API 的 429 拆成 RPM/TPM/RPD/并发四类,按维度重试并做多供应商故障转移。
文章指出,免费 LLM API 的 HTTP 429 不是单一问题,而是 RPM、TPM、RPD 和并发四种限制分别触发的结果,修复方式各不相同。作者建议先读响应体和响应头,例如 Groq 的 `x-ratelimit-*` 与 `retry-after`、Gemini 的 `quotaId` 和 `retryDelay`、OpenRouter 的窗口提示,再对症下药。在重试策略上,核心是遵守 `retry-after`、使用指数退避加抖动并限制次数,以及按 token 而非请求数来优化。结构性的解法是把免费层当成"池子的池子":同时持有多个 OpenAI 兼容密钥,一个窗口关闭就故障转移到下一个供应商,并按照限制的"形状"路由任务。作者最后强调记录每请求的供应商、模型、延迟、状态和限流头,一周日志就能定位真正的瓶颈。
每个免费 LLM API 在你碰到限额之前都表现得慷慨大方,直到某次 HTTP 429 把演示或批处理任务拦腰截断。多数教程止步于"加个重试循环",但在免费额度上做工程,真正有效的是按供应商、按层次拆解问题。

先判断你撞上的是哪一种限制
429 不是一个问题,而是四个。免费额度通常同时在多个维度上计量,修复方式取决于触发的是哪一个:
- RPM(每分钟请求数):请求太频繁,平滑发送有效,加容量没用。
- TPM(每分钟 token 数):几个长 prompt 就吃掉整分钟的配额,需要缩短上下文、限制 max_tokens。
- RPD(每日请求数):当天额度已尽,代码层面无解,只能把任务分摊到多天或多个供应商。
- 并发数:层级只允许一个在途请求,你却发了两个。用队列,别并行。
动手改代码之前,先读响应体和响应头。Groq 会返回 x-ratelimit-remaining-requests(按天)和 x-ratelimit-remaining-tokens(按分钟),外加 retry-after,429 本身就告诉了你哪个窗口空了、何时回来。Gemini API 返回 429 RESOURCE_EXHAUSTED,在 details[].quotaId 中指明被违反的窗口,并按分钟限制给出 retryDelay,其每日配额在太平洋时间午夜重置。OpenRouter 免费模型的每日上限在账户购买额度后会从小额度跳到更大额度,错误文本和 x-ratelimit-reset-requests 头会告诉你是哪个窗口关闭了。部分供应商什么也不给:如果 429 是裸的,就把所有窗口视为已关闭,按小时级别退避。
HTTP 429 与速率限制语义:429 是 RFC 6585 定义的 "Too Many Requests" 状态码,通常出现在 API 网关或服务端限流层,早于业务逻辑执行。它并非错误,而是一种流控信号,含义是"请求合法但超过了你当前窗口的配额"。语义上 429 属于可重试状态码,与 401(鉴权失败)、403(权限不足)本质不同——后两者重试多少次都没用,而 429 有可能在窗口刷新后自然恢复。因此客户端见到 429 的正确反应不是立刻换 key 或换供应商,而是先判断被违反的维度。多数供应商会通过 Retry-After、X-RateLimit-* 系列头,或响应体中的结构化字段(如 quotaId)告知是哪一类配额耗尽,忽略这些线索盲目重试往往会放大消耗,让本来只差几秒恢复的窗口雪上加霜。
重试要重试得像回事
三条规则覆盖大多数情况:
- 有
retry-after就照做。这是供应商在告诉你实情,猜时间只会更糟。 - 没有就指数退避加抖动:1s、2s、5s、10s,再加随机偏移,上限几分钟。对每日上限做循环重试毫无意义,3 到 5 次后就该停下并抛出错误。
- 数 token,别数请求。按 RPM 调好的重试循环在 TPM 才是真正瓶颈时依然会失败,因为重试本身又在每分钟烧掉更多 token。
指数退避与抖动:指数退避指每次重试前等待时间按固定倍数(通常为 2)增长,比如 1s、2s、4s、8s,直到达到上限。它的目的是在被限流的服务端与客户端之间拉开时间尺度,避免在高并发下形成"重试风暴"。仅指数退避还不够:如果大量客户端同时被拒,它们会在相同的退避时刻同步重试,形成周期性冲击。抖动(jitter)就是给每次等待加一个随机偏移,常见做法是取 [0, delay] 或 [delay/2, delay] 区间的随机值,把同一批客户端的重试时刻打散。结合上限(如几分钟)和最大重试次数(如 3 到 5 次)后,退避才真正可用。需要强调的是,退避只对 RPM、TPM、并发这类短窗口有效;对 RPD 这种当天归零的配额,任何退避都是徒劳,应当直接判失败或切换供应商。
别把全部希望押在一口井上
单个供应商的免费额度就是一个配额池,结构性的解法是把免费层当成"池子的池子":
- 同时持有多个 OpenAI 兼容密钥(Gemini、Groq、NVIDIA NIM、OpenRouter、Cloudflare Workers AI、Cerebras 等各自公布自己的上限),一个窗口关闭时就把请求故障转移到下一个供应商。由于它们都说 OpenAI 聊天格式,客户端代码不用改,只换 base URL 和 key。
- 按限制形状路由,而不只看可用性。夜间摘要任务需要 RPD 余量(Groq 的每日额度或 Gemini 的每日上限);交互式原型需要 RPM 平滑度;一次性抽取则可以放心烧掉按 token 限流的层级。
- 注意条款。一些免费层(Cohere 的试用密钥、Mistral 的 La Plateforme 免费层)明确只用于评估,不用于生产;OpenRouter 条款禁止转售 API 访问权。在往上搭产品之前先读清楚。
手写这层意味着要做供应商抽象、按供应商的窗口追踪、队列,以及为每一个加健康检查,这本身就是一个独立项目的大部分工作量。不想自己维护这层,也有现成路由可用:作者本人在做的 FreeLLMAPI 是一个开源、自托管的路由器,保管你的供应商密钥,处理 429 和带退避的重试,回退到其他供应商与模型,最后暴露一个 OpenAI 兼容端点。同样的工作可以用上面的手册手工完成,路由器只是让你只写一次并自托管。
OpenAI 兼容接口与供应商抽象:所谓 OpenAI 聊天格式,指请求体形如 {model, messages: [{role, content}]},响应体形如 {choices: [{message}]} 的 JSON 结构。Gemini、Groq、NVIDIA NIM、OpenRouter、Cerebras 等厂商大多提供这一格式的兼容端点,正是它让"只换 base URL 和 key"的多供应商故障转移成为可能。但兼容不等于完全一致:模型名、tool/function calling 字段、流式 chunk 的细节、错误对象结构往往有差异。因此在实际项目中,最好在兼容层之上维护一份按供应商的适配配置(模型名映射、超时、限流参数、是否支持某特性),而不是假设所有端点行为相同。这样才能在某一供应商限流或异常时安全切换,而不引入新的解析或行为 bug。
记录流量的形状
无论选哪条路,都按请求记录:供应商、模型、延迟、状态和限流响应头。一周日志就能告诉你实际撞的是哪个窗口,而这一个事实就决定了你需要的是平滑发送、更短的 prompt、第二个供应商,还是干脆上 5 美元的付费层。多数"我们需要更多配额"的问题,最后其实是"一个长 prompt 在循环里反复跑"的问题。429 是信息,先读懂它,再去重新生成密钥。
相关推荐

Claude Code+Codex多智能体系统实测:缓存率98%背后的真问题
开发者公布Claude Code+Codex多智能体系统7天实测:缓存率98%、输入输出比354:1,作者却卡在组织调度与输出比例,并追问行业基准与成本度量方法。

Cursor SDK 新功能:实时操控运行中的 AI 代理
Cursor SDK 新增 run.steer() 功能,允许开发者在 AI 代理运行中实时注入消息,调整执行方向。子代理遇 steer 时自动转入后台继续任务,为 AI 编程工作流带来更灵活的运行时干预能力。

如何评估AI生成的研究摘要?三个关键维度
AI生成的研究摘要读起来流畅,但事实未必可靠。本文基于Reddit讨论,梳理评估AI研究摘要系统的三个核心维度:来源可追溯性、事实一致性与不确定性处理,并探讨其对深度学习从业者的实践意义。