速率限制感知 AI API 网关:在 429 到达之前调整 RPM、TPM、突发和租户公平性
用于防止级联 LLM API 429 的实用网关架构:标准化提供商限制、在调度前估计代币压力、按租户保留配额、平滑流量斜坡并使节流可审核。
来自 LLM 提供商的 429 不仅仅是一个重试信号。在生产中,通常有证据表明您的应用程序已经失去了对准入、租户公平性、延迟或特定于提供商的配额核算的控制。
常见的修复方法(指数退避)是必要的,但并不完整。退避在提供商拒绝流量后做出反应。速率限制感知的 AI API 网关 应在请求离开系统之前调整流量:估计令牌压力、保留配额、隔离租户、对正确的工作进行排队、拒绝错误的工作以及在提供商限制更改时进行调整。
本文介绍了一种实用的网关配额调控器,供团队通过统一的 API.
将生产工作负载发送到多个 LLM 提供商读者问题:429 是多维的
许多团队将速率限制视为每分钟的单个请求数。 LLM API 很快就会打破这种假设。
当前提供商文档中的事实:
- OpenAI 记录了可能会在比宣传的每分钟限制更短的窗口内实施限制,因此即使平均分钟看起来安全,短时间突发也可能会失败。
- Azure OpenAI 配额按订阅、区域、模型和部署类型(以每分钟令牌数为单位)分配。将 TPM 分配给部署还会确定强制推理 RPM 限制,并且 RPM 与 TPM 的比率因模型而异。
- Azure OpenAI 还指出,速率限制令牌计算是在收到请求时估算的,与最终计费令牌计数不同。
- Anthropic 记录了单独的每分钟请求数、每分钟输入令牌数和每分钟输出令牌数限制。超出限制会返回带有重试标头的 429。
- Anthropic警告流量急剧增加可能会达到加速限制,并建议逐步加速。
- 对于大多数 Claude 模型,Anthropic 缓存读取输入令牌的文档不计入每分钟输入令牌限制,这意味着提示缓存可以更改有效空间。
- Google Gemini API 费率限制与项目使用级别相关,较高级别取决于结算设置、累计支出以及付款里程碑后的经过时间。
操作经验很明确:OpenAI 兼容的请求形状并不意味着 OpenAI 兼容的配额行为。多提供商网关需要比“重试 429”更丰富的内部配额模型。
设计目标:让准入控制成为网关的责任
速率限制感知网关应在分派请求之前回答五个问题:
- 哪个提供商、模型、部署、区域、项目或工作区将收到请求?
- 可能消耗多少请求、输入令牌、输出令牌和并发容量?
- 哪个租户、团队、API 键、客户或工作负载类应根据共享容量付费?
- 应该立即接受请求、短暂排队、降级、路由到其他地方还是拒绝?
- 提供商返回实际使用情况后应如何协调预留?
网关成为配额管理器。它不会取代提供商的限制。它使提供商的限制在您自己的系统中可见、可预测且公平。
构建标准化配额模型
首先定义可以代表主要提供商的内部限制器维度,而不会将它们强制归入一个误导性的范围。
推荐的限制器尺寸
- RPM: 每分钟请求数。
- 输入 TPM: 每分钟提示、消息、工具和上下文令牌。
- 输出 TPM: 每分钟完成令牌,为流式生成和长生成单独保留。
- 总 TPM:对于暴露组合令牌压力的提供商或部署很有用。
- 并发:活动请求、活动流或正在进行的作业。
- 流式传输持续时间:即使 RPM 较低,长期存在的流也可能占用连接和输出令牌余量。
- 特定于提供商的范围: Azure 订阅/区域/部署、Anthropic 工作区/模型类、Google 项目/层或 OpenAI 组织/项目/模型组。
不要隐藏提供商特定的维度。将它们标准化为通用架构,但保留足够的详细信息以便稍后解释拒绝。
{
"provider": "provider_a",
"model_profile": "fast-chat",
"provider_scope": {
"project": "prod",
"region": "us-east",
"deployment": "chat-large-01"
},
"limits": {
"rpm": 1200,
"input_tpm": 800000,
"output_tpm": 250000,
"concurrency": 200
}
}
此内部对象应显式配置,而不是单独从模型名称推断。提供商信息中心、帐户层级、区域部署和工作区设置都可以更改同一模型系列的有效容量。
在调度前估算令牌压力
提供商端速率限制通常发生在最终结算使用情况已知之前。您的网关应在发送流量之前进行同样的保守估计。
预检预订输入
- 序列化提示和消息长度。
- 特定于模型的标记化以及角色、工具、图像或结构化输出指令的开销。
max_completion_tokens或同等输出上限。- 此端点、租户、模型配置文件和请求类的历史完成率。
- 如果提示缓存可用且可测量,则预期的缓存读取令牌。
- 流式传输标志和预期流式传输持续时间。
简单的预订规则通常足以启动:
estimated_input_tokens = tokenize(request_messages) + model_overhead
estimated_output_tokens = min(
max_completion_tokens,
p95_historical_output_tokens_for_route
)
reserved_total_tokens = estimated_input_tokens + estimated_output_tokens
对于未知路由,请使用保守的默认值。为了稳定的生产路线,根据实际使用情况不断更新估算值。
预留,然后协调
配额预留不应成为永久性费用。将它们视为保留:
- 引用:估计输入和输出压力。
- 预留:调度前从相关令牌桶中扣除。
- 解决:将估算值替换为提供商报告的可用情况。
- 退款或借记:如果需要,将未使用的预留容量或超额费用退还至下一个窗口。
这对于长上下文和流式调用最为重要。如果您仅在分派之前检查输入 TPM,则流可以成功启动,然后会遇到输出令牌压力。单独保留输出余量可减少中流故障和失速风险。
使用分层令牌桶实现租户公平
单个全局限制器可以保护提供商帐户,但不能保护租户彼此。一项长上下文批处理作业可能会消耗共享 TPM,并导致其他团队的交互式请求失败。
使用分层令牌桶:
organization
└── tenant
└── team
└── api_key
└── model_profile
└── provider_deployment
请求必须传递每个相关存储桶。这样您就可以同时执行多项政策:
- 组织不能超出提供商的容量。
- 租户的消费不能超过其合同份额。
- API 密钥不能超出其预期环境或应用程序限制。
- 批量模型配置文件不能让交互式模型配置文件缺乏。
- 即使另一个部署有空闲配额,提供程序部署也不能超载。
公平共享与利用
建议:使用加权公平共享和受控突发借用。
严格的每租户上限很容易解释,但可能会浪费未使用的容量。突发借用允许租户临时使用共享池中的空闲配额,从而提高利用率。代价是复杂性:信息中心必须显示保证的内容、借用的内容以及借用的时间。
实用规则:
- 为每个租户提供有保证的基准。
- 允许从未使用的共享容量中突发借用。
- 出现更高优先级或有保证的流量时回收借用的容量。
- 切勿让借用的流量为有保证的流量创建提供商级 429。
在竞争之前将流量类别分开
并非所有请求都应具有相同的队列行为。将流量放入具有单独队列和配额池的模型配置文件中。
| 流量类别 | 典型政策 | 为什么 |
|---|---|---|
| 互动聊天 | 队列短、延迟预算低、快速失败或兼容回退 | 用户很快就会注意到尾部延迟 |
| 代理工作流程 | 中等队列、工具感知预算、输出空间 | 多步调用会放大代币压力 |
| 批量作业 | 队列较长、计划平滑、优先级较低 | 通常具有延迟容忍性且令牌较多 |
| 评估 | 专用配额,发生事件时暂停 | 可以产生突然的人工峰值 |
| 背景摘要 | 排队或延迟、严格的 TPM 上限 | 有用但很少紧急 |
排队可以提高成功率,但会增加尾部延迟。网关应该明确这种权衡。例如,交互式请求可能会等待长达 300 毫秒的配额,然后回退或失败。每晚的批处理作业可能会等待 20 分钟,但仍被视为成功。
将 429 标准化为单个错误架构
即使有良好的准入控制,提供商 429 仍然会发生。限制可能会发生变化,提供商的估计可能与您的不同,并且流量可能会比预期的激增。
将每个提供程序 429 标准化为网关错误对象:
{
"error": {
"type": "rate_limited",
"limiter": "output_tpm",
"provider": "provider_a",
"model_profile": "fast-chat",
"provider_model": "model-x",
"retry_after_ms": 2400,
"tenant_id": "tenant_123",
"api_key_id": "key_456",
"request_class": "interactive",
"estimated_input_tokens": 4200,
"estimated_output_tokens": 800,
"gateway_decision": "admitted_then_provider_rejected",
"fallback_allowed": false,
"trace_id": "trace_abc"
}
}
关键字段是gateway_decision。网关承认该请求后的 429 与网关在分派之前在本地拒绝的请求不同。第一个表明限制器校准问题。第二个表示有意保护。
根据提供程序标头进行调整,但不依赖它们
一些提供商会返回有用的标头,例如重试后或剩余容量指示器。可用时使用它们。
建议:提供商标头应调整您的本地调控器,而不是替换它。
原因:
- 标头可用性因提供商和端点而异。
- 标头不得公开每个限制器维度。
- Retry-after 告诉您何时重试,而不是下一个租户应该获得容量。
- 提供商方令牌估算值可能与您的结算或内部会计不同。
强大的实现会根据标头更新本地存储桶重新填充率和冷却时间,同时仍然在网关内强制执行租户、API 键、流量类别和提供程序部署限制。
为迁移和计划作业添加斜坡调节器
许多速率限制事件发生在计划更改期间:从一种模型迁移到另一种模型、更换提供商、启用新的代理工作流程或启动预定的评估运行。
建议:将流量增长视为可控的部署。
- 按租户、路线或流量百分比进行功能标记模型迁移。
- 为新提供商部署设置每分钟增长上限。
- 在数小时内逐渐预热流量,而不是立即切换所有流量。
- 当 429 速率、降级速率、队列深度或 p95 延迟超过阈值时暂停推出。
- 保留具有兼容性政策的紧急回滚路线,而不仅仅是备用模型。
预测:随着提供商路由模式、优先级和工作区级控制变得更加普遍,斜坡治理将成为标准网关功能,而不是事件响应脚本。
回退是一项政策决策,而不仅仅是容量决策
当一个提供商返回 429 时,路由到另一提供商可能是正确的答案。它也可能不安全。
回退可以更改:
- 输出质量和指令遵循。
- 上下文长度。
- 工具调用行为。
- 结构化输出可靠性。
- 数据保留和驻留状态。
- 成本和延迟。
配额管理器应询问兼容性层是否允许此请求类回退。如果不是,它应该排队或失败,并显示明确的本地速率限制响应,而不是默默地更改语义。
公开解释决策的配额信息中心
无人能理解的配额系统将被绕过。围绕运营问题构建仪表板:
- 哪些租户消耗的 RPM、输入 TPM 和输出 TPM 最多?
- 哪些模型配置文件正在排队、拒绝或回退?
- 哪个提供商范围是瓶颈:项目、区域、部署、工作区、模型类或帐户层?
- 网关估算值与提供商使用情况之间的差异有多大?
- 按提供商和限制器类型划分的重试后分配是什么?
- 提示缓存读取会创建多少有效空间?
- 哪些流量类别正在借用突发容量?
对于面向客户或面向合作伙伴的产品,公开安全控件:
- 每键速率限制。
- 每个团队的突发限制。
- 每个客户的每日上限。
- 租户或密钥紧急暂停。
- 针对 429 个峰值、队列增长和异常令牌压力发出警报。
- 用于转销商配额管理的合作伙伴 API 端点。
这将速率限制从神秘的提供商错误转变为团队API治理的可审核部分。
实施清单
第 1 阶段:观察和分类
- 每次调用的日志提供程序、模型、部署、区域、工作区、项目、租户、API 键和请求类。
- 使用重试后和原始错误元数据捕获提供程序 429。
- 分别记录估计和实际的输入/输出标记。
- 在遥测中分离交互式、批量、评估和后台流量。
第 2 阶段:本地准入控制
- 为 RPM、输入 TPM、输出 TPM、总 TPM 和并发创建内部限制器对象。
- 添加预检令牌估计。
- 在调度前预留配额,并在提供商使用量到达后进行协调。
- 当请求无法容纳其租户或提供商存储桶时在本地拒绝。
第 3 阶段:公平性和队列
- 将组织中的分层存储桶添加到提供商部署中。
- 分配有担保的租户份额并控制突发借款。
- 按流量类别创建单独的队列。
- 设置特定类别的最长等待时间和后备规则。
第 4 阶段:适应和运营
- 使用提供程序标头来调整冷却时间并重新填充假设。
- 为迁移和计划作业添加斜坡调节器。
- 公开配额信息中心和警报。
- 每周检查估算错误和搁浅配额。
可行的结论
如果您的网关仅重试 429 秒,则表示它在故障后运行。生产级 AI API 网关 应通过决定允许谁发送什么内容、何时发送以及针对哪个提供商配额来防止大多数速率限制失败。
从标准化限制器模型、预检令牌预留和流量类别队列开始。然后添加分层租户公平性、提供商标头适应和斜坡调节器。结果不仅仅是减少 429。您的工程、财务和客户支持团队实际上可以解释更清晰的容量分配、更可预测的延迟、更安全的迁移以及速率限制行为。