现场是这样的。groq 0.11 的 SDK 调 llama-3.3-70b-versatile,压测到 40 并发开始 429,响应里 code 是 rate_limit_exceeded,加 sleep 1 秒仍然复发,响应头的 x-ratelimit 数值看不懂。
中间走过弯路,把「多台机器共用同一把 key,配额是合并计算的」当成主因,改完现象没变。
排查方向其实有限,先把可能性排一排。RPM 和 TPM 是两套独立配额,token 先超同样返回 429;提示词很长,单次请求就吃掉大部分 TPM;重试没有退避,失败请求又把窗口占满。
第一件事是把响应头里的限流字段打出来
python -c "from groq import Groq;c=Groq();r=c.chat.completions.with_raw_response.create(model='llama-3.3-70b-versatile',messages=[{'role':'user','content':'hi'}]);print(dict(r.headers))"
接着用 curl 看 429 响应体的具体字段
curl -i https://api.groq.com/openai/v1/chat/completions -H "Authorization: Bearer $GROQ_API_KEY" -H "Content-Type: application/json" -d '{"model":"llama-3.3-70b-versatile","messages":[{"role":"user","content":"hi"}]}'
再往下把并发降到 5 并限制 max_tokens 再压一轮
python bench.py --concurrency 5 --max-tokens 256
末了按 retry-after 做指数退避
python -c "import time;time.sleep(int(headers.get('retry-after',2)))"
报错是间歇性的,我蹲守了半小时才抓到一次完整现场。
恢复的判定其实很直接。同样并发下 429 比例降到 1% 以内,x-ratelimit-remaining-tokens 始终大于单次请求消耗,重试间隔按 retry-after 递增。
提醒一点。429 先看响应头而不是盲加 sleep,remaining-tokens 和 remaining-requests 哪个归零,决定该减长度还是减并发。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。
