先分清这次 429,再调整队列
一则公开问题把异常称为 RateLimitError,日志里的具体错误码却是 lock_timeout。报告涉及用户反复访问付款页面,不能据此认定账户达到每秒请求上限。它证明异常名称容易误导诊断,但不代表这类故障的发生频率。[2]
Stripe 区分单位时间请求量、同时在途请求数与对象锁争用,三者对应不同的调度动作。[1]本文只讨论请求进入接口之前的流量管理,不重复幂等键保留、搜索可见性或导出完整性。
速率预算与并发预算不能互相代替
官方目前列出的全局速率为生产模式每秒一百次、沙箱每秒二十五次;单个接口默认每秒二十五次,另有说明的除外。这些是上限,不是可用吞吐承诺。同一命名接口下,不同对象标识仍共享接口限制。[1]
并发限制计算尚未结束的请求;耗时较长的列表读取和展开请求可能占用更多并发空间。[1]仅作算术示例:每秒开始十次请求、每次稳定耗时两秒,大约会有二十次重叠。这不是实测,也不是 Stripe 的并发配额。
建议用令牌桶控制开始速率,另用信号量控制在途数量,并让所有工作进程共享账户和接口预算。若每个副本各自领取整份额度,扩容就会放大总流量。令牌桶应平滑发送,而非鼓励瞬间冲到文档上限。
按原因选择调度动作
- 保存原始状态码、
Stripe-Rate-Limited-Reason、错误码、账户与模式、命名接口、相关对象、耗时,以及可取得的请求标识。先确认代理没有过滤响应头,再解释“没有原因头”。 - 遇到
global-rate,降低账户整体开始速率;遇到endpoint-rate,重点放慢对应接口,同时保留账户总预算。官方将两者列为不同限制范围。[1] - 遇到
global-concurrency或endpoint-concurrency,减少相应范围内的同时执行量,并查找慢请求,而不是只延长重试间隔。[1] - 遇到
resource-specific,核对资源对应的操作与时间窗口。例如 PaymentIntent 更新另有每对象每小时限制,通用每秒限速器不能覆盖所有资源约束。[1] - 没有原因头时,不要直接归为账户限流。官方说明这种 429 并非速率限制,可能是锁超时;还要在响应正文确认
lock_timeout。若原因仍不清楚,应保留未分类状态。[1]
串行化冲突对象,不必锁住整个账户
Stripe 建议同一对象的修改排队顺序执行;相关对象的并发访问也可能争锁。内部后台任务同样可能持锁,因此本地串行化不能保证消除全部锁超时。[1]
假设迁移任务与客户资料修改同时运行:若长列表请求触发 endpoint-concurrency,应减少迁移任务在途槽位,检查是否需要昂贵展开;若两个任务修改同一对象出现 lock_timeout,则把它们放进对象级顺序队列。无关对象仍可受控并行。两种情况都不应首先通过增加工作进程解决。
建议队列键包含账户上下文与共同业务对象。若不同子对象的操作实际触及同一父对象,应调查是否按父对象串行化。不能把“对象标识不同”当成绝无锁冲突的保证;这只是应用层设计建议,不是 Stripe 内部锁结构图。
恢复前检查清单
- 设置有界重试,采用官方建议的指数退避与随机延迟。检查所用开发工具包的重试配置:文档明确区分锁超时 429 与速率限制 429 的自动重试行为。[1]
- 重试仍须经过相同准入控制,不允许重试队列绕开账户和接口预算。分别统计首次调用与追加尝试。
- 观察原因分布、在途数、耗时、队列年龄和对象争用。保留原有写操作身份及核对流程,不要为绕过拥塞随意更换幂等键。
- 建议分别模拟各原因分支、响应头丢失、慢请求和重复对象修改。Stripe 不建议把沙箱压测当作生产容量证据,因为两者限额和延迟不同。[1]本文未执行这些测试。
来源与适用边界
核验日期:二〇二六年九月二十三日。本文仅研究公开文档,不代表真实账户测试或吞吐保证。调度建议以账户及接口具备使用资格为前提;所引页面没有为通用机制列出国家限制,具体产品的地区资格仍须单独确认。
- [1] Stripe 接口速率限制。发布与更新日期未注明;检索于二〇二六年九月二十三日。支持官方行为及当前文档上限,不代表特定账户容量承诺。
- [2] 处理 Stripe 速率限制异常。发布及更新于二〇二二年三月五日;检索于二〇二六年九月二十三日。历史第三方报告,仅用于证明实际需求,不用于核验当前开发工具包。