先看现象。用 FastAPI 0.111 写了一个 /chat 接口,内部用 AsyncOpenAI 调模型,压测 50 并发时三分之一请求返回 429,报错是 rate limit reached for requests,本地限流中间件并没有配。

把日志和配置对完,能解释这个现象的基本就这几处。上游按组织 RPM 限流,50 并发一秒钟就打满。另一种情况是接口没有做并发控制,突发全部打到上游。

另外,重试逻辑没加退避,429 之后立刻再发。

少数情况下是多个 worker 各自持有一个客户端,连接数放大。

先看响应头里的剩余配额

curl -s -D - http://localhost:8000/chat -o /dev/null | grep -i ratelimit

再往下加信号量把并发压到配额以内

python -c "import asyncio;print(asyncio.Semaphore(8))"

随后按 Retry-After 做指数退避

python -c "print([2**i for i in range(4)])"

等前面都确认过,再把突发请求放进队列削峰

python -c "print({'queue':'redis','max_inflight':8})"

恢复的判定其实很直接。同样 50 并发下 429 比例降到 1% 以下,P99 延迟不超过 8 秒,队列积压能被及时消费。

提醒一点。429 来自上游配额而不是本机瓶颈,先读响应头再谈扩容,盲目加 worker 只会把限流触发得更快。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。

作者 9823189