跳到主要内容

4 篇博文 含有标签「rate-limits」

查看所有标签

你从未进行过压测的每分钟 Token 上限

· 阅读需 11 分钟
Tian Pan
Software Engineer

Demo 成功了。Beta 测试也通过了。接着,正式发布带来的流量是平时的十倍,直接撞上了你从未进行过压测的每分钟 Token 配额,而在产品最受瞩目的时刻,所有超出上限的用户都收到了 429 错误。

这是无人排练过的故障模式。团队会偏执地对自己的服务器进行压测——副本、连接池、数据库索引——然后将每个请求都路由到一个存在于别人账户中的供应商配额,而那个上限他们从未真正触及过。限流不是一个在 try 块中捕获的错误。它是一个硬性的产品约束,如果你没有围绕它进行规划,那么产品发布之时,就是你第一次发现坑在哪里的时刻。

配额窗口机制重写后,这批夜间脚本是如何拖垮你的交互流量的

· 阅读需 13 分钟
Tian Pan
Software Engineer

一个稳定运行了十个月的 cron 任务是你系统中最危险的任务,因为其中的代码没变,你的代码也没变,唯一改变的是别人发布的、你们团队没人读的发行说明(release notes)中的一句话。那个每晚在 00:05 UTC 启动、在十分钟内清空工作队列并重新进入休眠状态的每晚 embedding 刷新任务,曾是教科书般的范例。它通过在用户醒来前占用几分钟刚重置的每分钟配额,并在当天的剩余时间内保持在每日配额之内,从而与白天的交互式流量和谐共存。接着,服务商重写了每日窗口的核算方式,保持了每分钟窗口不变,并保留了你客户端测试的所有签名。批处理任务依然稳定运行。但每晚 00:13 UTC,交互界面开始返回 429 错误。团队一直在追查一个根本不存在的、本应在一周后才开始的上游维护窗口。

Bug 从不在你的代码里。Bug 在于“每日限制”不再是前一天的意思,而你的调度程序固定在了一个与旧定义对齐的时钟边界上。这篇文章讨论的是:速率限制核算(rate-limit accounting)作为一种服务商可以在不破坏任何签名的情况下修改的契约;两个独立正确的调度是如何组合成拒绝服务模式的;以及如何通过架构手段让 cron 任务不再是一个连接到别人时钟上的定时炸弹。

你的评测套件也是生产负载:当每晚测试耗尽线上流量配额时

· 阅读需 12 分钟
Tian Pan
Software Engineer

一个团队最成功的 AI 功能在周二凌晨 2:14 宕机了。传呼机显示模型 API 在稳态下返回 429 错误。模型是健康的。供应商是健康的。团队自身的生产流量也是正常的。蚕食额度的是每晚运行的评测套件(eval suite)——正是团队在前一周引以为傲并进行扩展的那个套件。评测系统和产品共享同一个组织密钥(organization key),在那个夜晚,评测系统成了那个打破室友宁静的“吵闹邻居”。

评测系统并没有异常行为。它正在按照开发者的设计运行:针对生产模型标识符(identifier)进行一千个案例的测试,按节奏、按计划运行——这个计划因为已经静默运行了两年,早就被大家遗忘了。这次最终导致超限的扩展增加了三百个案例。该 PR 经过了评测负责人和 Prompt 负责人的审核。评审线程中没有一个人想到要问:这会消耗多少每日 Token 额度?

供应商配额在你的全球流量从未选中的时区重置

· 阅读需 10 分钟
Tian Pan
Software Engineer

你的每月 Token 配额在 00:00 UTC 重置。你最大的客户在东京,他们在 21:00 UTC(即当地时间第二天早上 6:00)达到峰值负载。当重置时刻到来时,东京的工作日已经在配额耗尽的降级方案中消耗了该周期的最后六个小时。429 错误看起来只是“偶发”,因为你仪表板上的 UTC 日历轴将每日重置边界隐藏在了普通的时间戳之中。

这不是速率限制(rate limit)的 Bug。这是一个日历 Bug。供应商为了结算方便选择了一个重置时钟,而你流量的地理分布决定了哪些客户会分配到周期末尾的空窗期。那些将配额定价为统一资源的团队,正基于一个用户从未见过的日历来进行配额分配。