你的聊天产品已经在 1.5 秒的 p99 延迟 SLO 下平静地运行了数月。请求率平稳,prompt 大小平稳,模型也未曾改变。接着,在某个周二下午,p99 突然飙升至 4.8 秒并保持在那里。值班排查发现聊天路径(chat path)没有任何异常:同样的每分钟请求数,同样的中位 prompt 长度(约 800 token),SDK 的重试行为也完全一致。聊天服务当天的部署日志为空。故障持续了六个小时。
原因出在另一个团队的代码库中。那天早上,一个长文本摘要功能上线了,使用的是同一个组织密钥(organization key),其平均 prompt 为 12,000 token。他们的请求率并不高 —— 每分钟仅几百次 —— 但每次调用消耗共享的每分钟 token(TPM)预算的速度比你的快 15 倍。供应商的限流在聊天路径上触发了,因为聊天路径与摘要团队共用同一个刚刚被掏空的“桶”。没人动过你的代码,没人超出计划的容量,而你的 SLO 现在却成了你的团队从未读过的工作负载的函数。
这就是共享每分钟 token(TPM)限制对多产品组织的影响。供应商给你一个衡量容量的单位,而你的团队则用另一个单位进行规划。在新的工作负载改变比例之前,这种核算缺口(accounting gap)是隐形的。
供应商限流的单位并非你规划的单位
主流供应商 —— OpenAI、Anthropic、Google —— 都在组织(organization)级别而非 API 密钥级别强制执行每分钟 token 数(TPM)限制。同一组织下的每个密钥都从同一个 TPM 池中支取。OpenAI 直接在文档中说明了这一点:在同一个组织下创建的所有密钥共享相同的 RPM、TPM、RPD 和 TPD 池。Anthropic 按组织而非密钥强制执行速率限制,使用令牌桶算法,持续补充直至达到组织上限。
你与供应商协商的数字 —— 或者你通过消费升级到的阶梯 —— 是以每分钟 token 数为单位的。TPM 是真实的预算,而你的应用程序规划通常并非如此。
大多数应用团队根据供应商不限流的两个单位来思考容量:每分钟请求数(RPM)和每月美元开销。RPM 是负载均衡器和自动扩缩容关注的指标。美元是财务合作伙伴关注的指标。这两者都不是限流触发的单位。一个在受 TPM 限制的 API 上持有 RPM 预算的团队,其容量规划的单位是错误的。一旦另一个团队的 prompt 大小发生变化,该规划就会因 prompt 大小的偏移比例而失效。
数学逻辑非常直观。如果你的聊天负载以 1,000 RPM 运行,平均 prompt 为 800 token,你将消耗 800K TPM。如果同级的工作负载以 500 RPM 运行,平均 prompt 为 12,000 token,它将消耗 6M TPM。聊天团队的请求率没有变化,但聊天团队现在看到的每分钟 token 剩余空间比昨天少得多。当组织桶发生限流时,它会限制 SDK 恰好请求的下一个对象 —— 而带有指数退避(exponential backoff)的 SDK 重试会将聊天路径的 p99 推高到数秒,且没有任何信号表明聊天路径本身出现了异常。
为什么值班排查一无所获
聊天团队值班人员首先会检查聊天服务。仪表盘很正常。请求数正常。prompt 大小分布正常。重试仪表盘显示有一个峰值,但导致重试的输入源自上游 —— 它是供应商返回的 429 错误,而这些 429 是由聊天团队无法看到的流量引起的。
跨团队限流归责在结构上非常困难,因为失败点距离拥有 SLO 的团队有一步之遥。聊天团队负责 p99 延迟。摘要团队负责自己的请求率、prompt 大小分布和账单。两个团队都达到了各自的内部预算。但总消耗超过了供应商的 TPM 上限。没有任何一个团队的个人计划是错误的。
这是一种“每个人内部都逻辑自洽,但系统整体崩溃”的失败模式。每个团队的容量规划都符合其协商的预算。但组合起来却失效了,因为没有哪个团队的预算单位与供应商限流的单位一致。聊天团队以 RPM 预算,摘要团队以美元和 RPM 预算,供应商以 TPM 限流。三个单位,一个桶,没有负责人。
本能的修复方案 —— 提升供应商层级 —— 只是争取了时间,但并没有修复结构问题。下一次 prompt 大小的转变、下一次新的工作负载、下一次在同一个组织密钥上发布的产品,都会在更高的绝对预算下重现同样的模式。单位不匹配才是 bug,层级上限只是症状缓冲器。
弥合差距的应用端模式
修复方案是在内部以供应商限流的相同单位来衡量容量。目前有四种模式在生产环境中发挥作用,它们通常结合使用。
在调用触发前执行的按团队 token 分配。 将供应商组织级别的 TPM 转换为内部规划工具可以本地强制执行的按团队分配。摘要团队获得一个 TPM 预算,聊天团队获得一个 TPM 预算。总和(加上预留空间)等于供应商的上限。每个团队的内部限流会在供应商限流之前触发,超过 TPM 分配的团队会在自己的仪表盘中看到限流,而不是表现为别人的延迟峰值。这就是 Kubernetes ResourceQuota 在集群级别的工作方式,这种类比可以完美映射到 LLM 容量:你付费的单位就是你做预算的单位。
在应用程序和供应商之间建立内部 token 预算网关。 来自 Portkey、TrueFoundry 和类似厂商的生产级 AI 网关展示了行业中趋于一致的模式:一个以 (tenant, workload, model) 为键的令牌桶速率限制器,按每分钟 token 数而非每分钟请求数进行限流。网关估算每个请求的 token 成本 —— 输入 token 是确切知道的;输出 token 则通过 max_tokens 或历史平均值来估算 —— 并在转发给供应商之前决定是否准入。当网关的本地 TPM 分配耗尽时,它向应用程序返回 429 错误,并附带一个根据桶补充速率计算出的 Retry-After 响应头。应用程序针对自己的限流进行退避,而不是针对供应商,从而使供应商的 TPM 上限是从下方趋近而非直接撞上。
将“其他租户的 token 消耗”列为协变量的 SLO 模型。 大多数延迟 SLO 模型假设“喧闹邻居”(noisy-neighbor)风险受限于平台的隔离保证。但在共享的 LLM 组织密钥上,没有隔离保证。诚实的 SLO 模型会记录下这一点:聊天路径的 p99 是聊天路径 token 消耗、摘要路径 token 消耗以及共享该桶的所有其他工作负载的函数。错误预算中包含了一个跨租户流量的协变量项。仪表盘在显示聊天路径延迟的同时,也会显示组织级别的 TPM 利用率。告警会在组织 TPM 利用率超过 80% 时触发,而不是等到聊天延迟超过 SLO —— 因为延迟违约是滞后指标,而桶利用率是领先指标。
为每类工作负载设置独立的组织密钥。 当隔离性比聚合效率更重要时,结构化的修复方案是停止共享桶。为每个具有明显不同 prompt 大小特征的工作负载类别配置独立的供应商组织或工作区(workspace)。Anthropic 和 OpenAI 都支持组织内的工作区级速率限制;一些团队更进一步,为批处理和交互式工作负载运行完全独立的组织。代价是运维开销 —— 更多需要轮转的密钥,更多需要对账的账单关系 —— 以及失去了跨工作负载统计复用的效率。好处是聊天团队的 SLO 不再是摘要团队 prompt 大小的函数。这种收益是否值得这些开销,取决于各工作负载脉冲式爆发重合的频率。
运行六个月后的景象
采用令牌网关(token-gateway)和按团队分配(per-team allocation)模式的团队通常会在第一个季度发现几件事。首先是网关对输出令牌(output tokens)的预估误差是导致 429 误报的主要原因。一个 max_tokens 被保守地设定为 4,000 但通常只返回 200 个令牌的请求,会被网关计为消耗了 4,000 个令牌预算。解决方法是跟踪每个端点的实际输出令牌分布,并使用历史 p95 值作为预估,而不是使用配置的 max_tokens 上限。这在不改变供应商层级的情况下,能显著提升有效吞吐量。
第二个发现是,令牌感知型熔断器比请求感知型熔断器更重要。如果一个工作负载的令牌消耗速率增长快于其请求速率——例如长上下文回归、由于新系统提示词堆积导致的提示词膨胀、不断增长的少样本(few-shot)示例集——它就是下一个“嘈杂邻居”(noisy neighbor)。熔断器应根据每个工作负载的令牌速率而非请求速率触发。在代码审查阶段就关注提示词大小仪表盘和延迟仪表盘的工程团队,能在生产环境之外拦截提示词膨胀导致的回归。
第三个是更安静的文化转变。团队间的容量规划对话开始将 TPM 作为通用货币。引入新工作负载类别的产品发布会根据组织的 TPM 余量(headroom)而非 RPM 余量进行评审。共享账单仍然是一个限制因素,但共享的节流阀(throttle)变成了束缚性限制,团队会针对它进行明确规划。过去在事故发生时才出现的跨团队指责,现在提前到了设计评审阶段。
认知重构
架构层面的认知虽小,影响却很深远。供应商节流的单位就是你的应用程序必须规划的单位。如果供应商以每分钟令牌数(TPM)定义容量,而你以每分钟请求数(RPM)定义预算,那么你构建的 SLO 的波动将由共享账单的每一个其他团队决定。解决方法不是去协商一个更高的上限,而是用与外部上限强制执行时相同的单位来定义内部容量,并使该单位在团队边界上可见。
做对这一点的团队会将供应商的 TPM 限制视为一种共享资源,需要像对待 Kubernetes CPU 份额、S3 请求配额或任何其他多租户容量上限一样进行分配管理。令牌预算网关、按团队分配和跨团队协变量模型并不新奇——它们只是披着令牌外壳的成熟 SRE 模式。而做错的团队,其组织级仪表盘显示 RPM 尚有余量,而 TPM 桶却已悄悄耗尽,当有人在同一个 Key 上发布长上下文功能时,他们的聊天 SLO 就会在毫无预警的情况下崩溃。
聊天服务的 p99 从来不是在衡量聊天服务本身。它衡量的是最近哪个工作负载抽干了令牌桶。在令牌桶拥有明确的主人之前,SLO 也同样无主。
会员专享
余下内容仅对会员开放。
会员可读完整内容 —— 每一个公开发布的观点背后,那些框架、决策与推理的全貌。
- —完整文章,包含未公开存档的部分
- —可落地的工作框架,附带权衡与决策依据
- —新文章抢先看,先于公开发布
随时取消 · 一次订阅,畅读全部