跳到主要内容

你的延迟 SLO 取决于其他团队的 Prompt 大小

· 阅读需 11 分钟
Tian Pan
Software Engineer

你的聊天产品已经在 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,层级上限只是症状缓冲器。

加载中…
References:Let's stay in touch and Follow me for more thoughts and updates