客户端重试预算:别让重试风暴打垮自己的服务器
背景与问题
客户端「失败了重试」看似稳健,但全量用户同时重试就是 DDoS 自己——服务器抖一下被放大成宕机。solo 后端尤其扛不住重试风暴。整理客户端侧的最小重试纪律。
发现
(来源访问日期均为 2026-09-17)
- 事实(AWS Builders' Library):Amazon 的标准=每次远程调用设 timeout、在总超时内预算重试次数、full jitter 打散重试同步。AWS SDK 默认内置指数退避+jitter。
- 事实(AWS 架构博客经典文):数学上 full jitter 优于 equal jitter 与纯指数退避——退避只降频率,jitter 防止全体客户端同时刻重试(thundering herd)。
- 事实(重试风暴解说的共识清单ほか):①重试预算(retries ≤ 最近成功流量的 ~10-20%,token bucket 封顶)②总次数上限 2-4 次 ③客户端 timeout < 服务器 timeout(防级联堆积)④尊重
Retry-After头与 429/503 ⑤熔断器:连续失败就停止重试。 - 推测:solo 产品的重试事故几乎都来自「网络库默认无上限重试」——一次部署抖动被全量客户端放大成雪崩。重试是客户端的礼貌问题,不是服务器能兜的。
结论
- 网络库三件套:指数退避+full jitter、上限 3 次、总 deadline 10 秒——默认值写进共用网络层,业务代码不各自写重试。
- 重试预算:客户端侧简单实现=「过去 1 分钟重试成功率 <50% 就暂停重试」(失败中的重试无意义),或全局 token bucket(如每分钟最多 20 次重试)。
- 分级纪律:GET 可重试;POST/支付类默认不自动重试(幂等键或用户手动重发)——与 opc-receipt-validation-minimum 的支付路径一致。
- 服务器配合:过载时返回 429+Retry-After,客户端必须遵守——这是防止自伤的最后闸门(服务器已在 opc-edge-api-workers 的限流中间件里)。
待办 / 下次继续
关联
opc-edge-api-workers opc-receipt-validation-minimum opc-cron-design-minimum