高并发场景下,如何解决 LLM 接口限流?
解决思路不是“把 429 重试成功”,而是把 Provider 的 请求数、Token 吞吐和在途连接建模为有限容量,在请求真正发出前完成准入、调度、削峰与降级。429 只应当是本地预测偏差的最后反馈。
1. 429 不是普通网络失败:它会触发重试风暴
低流量时,“休眠几秒再重试”偶尔有效。高并发时,大量实例会在相近时刻重试,失败流量继续消耗额度,导致 429 从局部问题扩散为排队、超时和全链路雪崩。
错误路径 多层各自重试
业务层 × SDK × Gateway × 队列消费者都重试 3 次,最坏会把一次请求放大为 3⁴ = 81 次 出站尝试。
429
正确路径 出站前先调度
一个统一 Gateway 保有全局预算账本。能同时获得 RPM、Token 和并发槽的请求才出站;否则按 Deadline 进入队列、降级、切路由或快速失败。
先隔离 noisy neighbor,保护公共容量。
输入 Token + 预留输出 Token + 请求额度 + 并发槽。
排队只削峰,不制造容量;过期任务直接处理掉。
2. LLM 容量模型:同时受四种资源约束
普通 HTTP 接口常只看请求数;LLM 的一条长上下文、长流式回答可能占用数万个 Token 和几十秒连接。可持续速率取四个上界中的最小值。
大量短问答最容易先耗尽。每一次真正发出调用,通常不退还。
长 Prompt、RAG 文档、历史对话造成的核心约束。
长生成、思考/推理、流式回答持续消耗吞吐。
慢响应和长流式连接会长期占着并发槽。
变量含义
R:RPM;TI / TO:输入 / 输出 TPM;I / O:平均输入 / 输出 Token;C:并发槽;S:平均耗时秒数。
为什么不能取 100%?
为 Token 长尾、突发流量、估算误差、故障切流留余量。生产上应看 P95/P99 Token 与延迟,不能只用平均值。
交互演示:没有准入 vs 有全局准入
点击模式,观察请求在“Provider 前”被如何处理。
Gateway
Provider
3. 在 LLM Gateway 前完成全局准入
容量账本不能只放在每个 Pod 的内存里:10 个 Pod 各自认为还有一份配额,实际流量就会被放大 10 倍。使用 Redis + Lua 原子操作,或由中心调度器发放短周期额度租约。
Token 必须“预占 + 对账”
先用 tokenizer 计算输入 Token;输出按任务类型、历史分位数和 max_tokens 预留。调用完成后用真实 usage 对账:少用返还 Token 差额,超出则补扣并更新估算系数;流结束、取消、超时释放并发槽。
多资源要一次拿齐
不能 RPM 够了就先占请求额度、但 TPM 不够;也不能 Token 够了就提前占住并发槽等待。资源必须在同一原子事务中获取,否则会产生锁住资源却无法执行的死等。
4. 用计算器估算可持续速率
下面是容量规划的第一步:调节典型负载参数,观察是谁决定了系统上限。注意,这只是保守起点,线上还需用 P95/P99 和真实 headers 校准。
—
5. 队列只削峰,不能创造容量
短时峰值可以等待额度恢复;如果到达速率长期大于 Provider 放行速率,无限队列只会把“立即失败”变成“很久以后失败”,还会消耗内存、连接与用户耐心。
⏳ 有界 + Deadline
在线请求设置短 Queue Deadline。预计无法在时限内获得预算时,返回 429/503 + Retry-After,而不是无止境等待。
📬 同步转异步
报告、评测、清洗等可异步任务返回 task ID,写入持久化队列;任务过期要主动丢弃,不能“拿到额度才执行过期任务”。
↔ 公平调度
拆分在线 / 交互 / 离线 Lane,再按租户权重、优先级和 Token 成本用 WFQ 或 DRR 出队,避免长任务堵住短任务。
6. 429 的正确处理:受控重试 + 自适应收缩
重试的准入条件
- 只重试可恢复的 429、部分 5xx、网络瞬断;鉴权、参数错、余额不足、硬配额直接失败或切方案。
- 优先遵循
Retry-After与 reset headers;缺失时才采用 Full Jitter 指数退避。 - 检查原始请求是否还剩足够 Deadline,且没有耗尽 Retry Budget。
- 重试任务释放并发槽,进入延迟队列;不要原地
sleep占着 Worker。
重试责任只能在一层
推荐 Gateway 成为唯一协调者:关闭或收紧 SDK 自动重试,业务层不再盲目补偿。对有外部副作用的 Agent 步骤,必须携带幂等键和步骤状态,避免重试间接导致重复发消息、下单或写库。
读取反馈
分类错误;读取 Retry-After / reset / remaining 与真实 usage。
判断预算
检查 Deadline、Retry Budget、幂等性与备用模型是否独立配额。
延迟重入
释放并发槽 → 延迟队列 → 到期后重新参与准入,而非直接冲上游。
7. 先减少需求,再讨论如何放行
最便宜的一次模型调用,是没有发生的那次。限流治理不只是在拥塞时“拦住请求”,更要减少请求数和 Token 消耗。
🗃️ 缓存与合并
精确缓存处理完全相同请求;语义缓存用于能容忍近似答案的场景;热点并发请求通过 Singleflight 合并在途调用,防止缓存击穿。
✂️ Token 优化
压缩 System Prompt、裁剪无关历史、长会话摘要、降低 RAG top_k、为不同任务设置合理的输出上限;固定前缀优先走 Provider Prompt Cache。
🤖 Agent 预算
一个入口可扇出 Planner、Worker、Judge 多次调用。为 Agent 设置最大步骤数、最大并行分支与总 Token Budget;Embedding、评测、离线摘要尽量批处理。
8. 路由与降级:围绕业务价值,而不是只看可用性
主模型紧张时,Router 根据复杂度、质量要求、剩余额度、延迟和成本选择小模型、其他区域或其他 Provider。前提是备用路径真正独立,并经过协议适配和回归评测。
9. 用监控与压测闭环校准真实容量
必须按维度拆分的指标
- Provider / 模型 / 区域 / 业务线 / 租户的 RPM、输入输出 TPM 利用率与剩余额度
- Token 预占与实际 usage 的偏差、in-flight、TTFT、完整延迟、P95/P99
- 队列深度、最老任务年龄、过期丢弃数、拒绝率与 Retry-After
- 429 原因、重试放大系数、熔断状态、Fallback / 降级比例、缓存命中与单请求成本
压测必须覆盖真实“坏形态”
- 突发短请求:验证 RPM 和 Token Bucket 是否平滑削峰
- 超长上下文、长流式输出:验证输入/输出 TPM 与并发槽是否准确
- Agent 扇出、热点缓存击穿:验证调用放大和 Singleflight
- 注入 429、慢响应、备用模型故障:验证队列是否清空、Retry Budget 与降级质量
10. 生产落地清单
第一阶段:先止血
- 统一 429 处理层,关闭重叠自动重试;加 Retry Budget、Full Jitter 和 Deadline。
- 按 Provider + 模型 + 区域隔离熔断,避免局部限流扩大为全局不可用。
- 增加请求、Token、并发、队列、429 维度的观测与告警。
第二阶段:建立控制面
- Gateway 前置统一准入;使用 Redis/Lua 或额度租约实现多实例原子配额。
- 实现输入 Token 计算、输出预占、真实 usage 对账和流式连接释放。
- 引入有界优先级队列、Deadline、背压、异步任务和租户公平调度。
第三阶段:提升有效容量
- 精确缓存、语义缓存、Singleflight、Prompt Cache、上下文压缩和输出上限。
- 为 Agent 限制步骤、并发分支、总 Token;把离线任务批处理。
- 按任务价值路由到大小模型、独立 Provider 与适当的异步路径。
第四阶段:持续校准
- 用 response headers 和 usage 校准本地桶;以 P95/P99 而非平均值规划。
- 用 AIMD 自适应调节出站速率和并发;定期演练 429、慢响应与备链路故障。
- 需求长期超限时,走提额、预置吞吐或自建容量,而非继续堆重试。