429 表示“慢一点”,而不是“您没钱了”。区别很重要:前者需要等待,后者需要充值;混淆两者会让您在错误的方向上调试数小时。
错误
响应(HTTP 429)
{
"type": "error",
"error": { "type": "rate_limit_error",
"message": "Number of requests has exceeded your rate limit" }
}原因和解决方法一览
| 原因 | 解决方法 |
|---|---|
| 每分钟请求数超过账户限制 | 在客户端排队并限制并发,而不是一次性发出所有请求。 |
| 每分钟令牌数超过限制 | 长提示会在请求数配额耗尽之前很早消耗令牌配额。减少上下文或拆分工作。 |
| 多个进程使用同一个密钥 | 限制针对的是密钥,而不是进程。并行 worker 会共同消耗同一配额。 |
| 没有退避的重试 | 立即重试会让您持续处于超限状态。必须使用带抖动的指数退避。 |
收到 retry-after 时请遵守它
当响应包含 retry-after 标头时,它不是建议,而是请求再次被接受前的确切等待时间。等待更短必然会再次收到 429。
retry_after.py
import time
from openai import APIStatusError
try:
resp = client.chat.completions.create(model=MODELO, messages=msgs)
except APIStatusError as e:
if e.status_code == 429:
espera = float(e.response.headers.get("retry-after", 5))
time.sleep(espera)
resp = client.chat.completions.create(model=MODELO, messages=msgs)
else:
raise在源头限制并发
最常见的原因不是总量,而是突发:同一时刻发出 20 个请求会超过限制,而在一分钟内分散发出 60 个请求却不会。信号量可以解决单靠重试无法解决的问题。
concorrencia.py
import asyncio
LIMITE = asyncio.Semaphore(4) # no máximo 4 chamadas simultâneas
async def chamar(msgs):
async with LIMITE:
return await client.chat.completions.create(
model=MODELO, messages=msgs)确认是限制,而不是余额
429 从不表示缺少额度——那是 402。如果日志混合了两者,请先按状态码分开再调查:429 的修复方式是调整时序,402 的修复方式是充值。重复发送 402 会永远失败。
如果你通过 Kunavo 调用
在 Kunavo,限制按密钥计算,余额则是独立的预付钱包,因此两种情况会返回不同状态:429 表示速率限制,402 表示余额不足以支付调用——两者不会互相伪装。被拒绝的请求不会收费。 决定每次调用消耗多少余额的令牌费率,见 我们的 Claude API 价格指南.
常见问题
429 意味着我的额度用完了吗?
不。余额不足是 402。429 讲的是速度:您在短时间内发送了过多请求或令牌,等待即可解决。
我应该等待多久?
如果有 retry-after 标头,就等待准确的时间。如果没有,从 1–2 秒开始进行带抖动的指数退避,直到 30–60 秒的上限。
提高限制能解决问题吗?
如果流量确实很高,提高限制会有帮助,但大多数 429 来自短时间内的突发流量。限制并发通常无需改变任何限制即可解决。