← 关联知识节点:模型调用与容错:让失败变成看不见的内部事件
交互工具 · 原理

重试风暴 · 退避与抖动

Agent 一轮要调几十次 API,429 限流必然成批出现。失败后怎么重试?三个客户端同时被拒、同时重拨,服务刚喘口气又被砸回去。切三种策略重放同一场风暴:固定间隔永远满载、指数退避摊薄了频率但整点扎堆、加了抖动才真正散成细雨。

纯前端事件驱动模拟:50 客户端、服务 2s 恢复、每 0.25s 容量 10 个,带种子可复现;错误分流规则(429 只等不换 / 529 到顶换 fallback / 4xx 直接抛)与知识库《调用层》逐条对齐,零 API。

服务过载,50 个客户端在 t=0 同时被拒(429),各自安排重试。 服务 t=2s 恢复,之后每 0.25s 只能处理 10 个请求—— 切三种重试策略,看谁把重砸变成细雨。

重试时间轴(每行一个客户端)

被拒(再吃 429) 成功
服务恢复 t=2s客户端 #1 t=1.00s 被拒客户端 #1 t=2.00s 成功客户端 #2 t=1.00s 被拒客户端 #2 t=2.00s 成功客户端 #3 t=1.00s 被拒客户端 #3 t=2.00s 成功客户端 #4 t=1.00s 被拒客户端 #4 t=2.00s 成功客户端 #5 t=1.00s 被拒客户端 #5 t=2.00s 成功客户端 #6 t=1.00s 被拒客户端 #6 t=2.00s 成功客户端 #7 t=1.00s 被拒客户端 #7 t=2.00s 成功客户端 #8 t=1.00s 被拒客户端 #8 t=2.00s 成功客户端 #9 t=1.00s 被拒客户端 #9 t=2.00s 成功客户端 #10 t=1.00s 被拒客户端 #10 t=2.00s 成功客户端 #11 t=1.00s 被拒客户端 #11 t=2.00s 被拒客户端 #11 t=3.00s 成功客户端 #12 t=1.00s 被拒客户端 #12 t=2.00s 被拒客户端 #12 t=3.00s 成功客户端 #13 t=1.00s 被拒客户端 #13 t=2.00s 被拒客户端 #13 t=3.00s 成功客户端 #14 t=1.00s 被拒客户端 #14 t=2.00s 被拒客户端 #14 t=3.00s 成功客户端 #15 t=1.00s 被拒客户端 #15 t=2.00s 被拒客户端 #15 t=3.00s 成功客户端 #16 t=1.00s 被拒客户端 #16 t=2.00s 被拒客户端 #16 t=3.00s 成功客户端 #17 t=1.00s 被拒客户端 #17 t=2.00s 被拒客户端 #17 t=3.00s 成功客户端 #18 t=1.00s 被拒客户端 #18 t=2.00s 被拒客户端 #18 t=3.00s 成功客户端 #19 t=1.00s 被拒客户端 #19 t=2.00s 被拒客户端 #19 t=3.00s 成功客户端 #20 t=1.00s 被拒客户端 #20 t=2.00s 被拒客户端 #20 t=3.00s 成功客户端 #21 t=1.00s 被拒客户端 #21 t=2.00s 被拒客户端 #21 t=3.00s 被拒客户端 #21 t=4.00s 成功客户端 #22 t=1.00s 被拒客户端 #22 t=2.00s 被拒客户端 #22 t=3.00s 被拒客户端 #22 t=4.00s 成功客户端 #23 t=1.00s 被拒客户端 #23 t=2.00s 被拒客户端 #23 t=3.00s 被拒客户端 #23 t=4.00s 成功客户端 #24 t=1.00s 被拒客户端 #24 t=2.00s 被拒客户端 #24 t=3.00s 被拒客户端 #24 t=4.00s 成功客户端 #25 t=1.00s 被拒客户端 #25 t=2.00s 被拒客户端 #25 t=3.00s 被拒客户端 #25 t=4.00s 成功客户端 #26 t=1.00s 被拒客户端 #26 t=2.00s 被拒客户端 #26 t=3.00s 被拒客户端 #26 t=4.00s 成功客户端 #27 t=1.00s 被拒客户端 #27 t=2.00s 被拒客户端 #27 t=3.00s 被拒客户端 #27 t=4.00s 成功客户端 #28 t=1.00s 被拒客户端 #28 t=2.00s 被拒客户端 #28 t=3.00s 被拒客户端 #28 t=4.00s 成功客户端 #29 t=1.00s 被拒客户端 #29 t=2.00s 被拒客户端 #29 t=3.00s 被拒客户端 #29 t=4.00s 成功客户端 #30 t=1.00s 被拒客户端 #30 t=2.00s 被拒客户端 #30 t=3.00s 被拒客户端 #30 t=4.00s 成功客户端 #31 t=1.00s 被拒客户端 #31 t=2.00s 被拒客户端 #31 t=3.00s 被拒客户端 #31 t=4.00s 被拒客户端 #31 t=5.00s 成功客户端 #32 t=1.00s 被拒客户端 #32 t=2.00s 被拒客户端 #32 t=3.00s 被拒客户端 #32 t=4.00s 被拒客户端 #32 t=5.00s 成功客户端 #33 t=1.00s 被拒客户端 #33 t=2.00s 被拒客户端 #33 t=3.00s 被拒客户端 #33 t=4.00s 被拒客户端 #33 t=5.00s 成功客户端 #34 t=1.00s 被拒客户端 #34 t=2.00s 被拒客户端 #34 t=3.00s 被拒客户端 #34 t=4.00s 被拒客户端 #34 t=5.00s 成功客户端 #35 t=1.00s 被拒客户端 #35 t=2.00s 被拒客户端 #35 t=3.00s 被拒客户端 #35 t=4.00s 被拒客户端 #35 t=5.00s 成功客户端 #36 t=1.00s 被拒客户端 #36 t=2.00s 被拒客户端 #36 t=3.00s 被拒客户端 #36 t=4.00s 被拒客户端 #36 t=5.00s 成功客户端 #37 t=1.00s 被拒客户端 #37 t=2.00s 被拒客户端 #37 t=3.00s 被拒客户端 #37 t=4.00s 被拒客户端 #37 t=5.00s 成功客户端 #38 t=1.00s 被拒客户端 #38 t=2.00s 被拒客户端 #38 t=3.00s 被拒客户端 #38 t=4.00s 被拒客户端 #38 t=5.00s 成功客户端 #39 t=1.00s 被拒客户端 #39 t=2.00s 被拒客户端 #39 t=3.00s 被拒客户端 #39 t=4.00s 被拒客户端 #39 t=5.00s 成功客户端 #40 t=1.00s 被拒客户端 #40 t=2.00s 被拒客户端 #40 t=3.00s 被拒客户端 #40 t=4.00s 被拒客户端 #40 t=5.00s 成功客户端 #41 t=1.00s 被拒客户端 #41 t=2.00s 被拒客户端 #41 t=3.00s 被拒客户端 #41 t=4.00s 被拒客户端 #41 t=5.00s 被拒客户端 #41 t=6.00s 成功客户端 #42 t=1.00s 被拒客户端 #42 t=2.00s 被拒客户端 #42 t=3.00s 被拒客户端 #42 t=4.00s 被拒客户端 #42 t=5.00s 被拒客户端 #42 t=6.00s 成功客户端 #43 t=1.00s 被拒客户端 #43 t=2.00s 被拒客户端 #43 t=3.00s 被拒客户端 #43 t=4.00s 被拒客户端 #43 t=5.00s 被拒客户端 #43 t=6.00s 成功客户端 #44 t=1.00s 被拒客户端 #44 t=2.00s 被拒客户端 #44 t=3.00s 被拒客户端 #44 t=4.00s 被拒客户端 #44 t=5.00s 被拒客户端 #44 t=6.00s 成功客户端 #45 t=1.00s 被拒客户端 #45 t=2.00s 被拒客户端 #45 t=3.00s 被拒客户端 #45 t=4.00s 被拒客户端 #45 t=5.00s 被拒客户端 #45 t=6.00s 成功客户端 #46 t=1.00s 被拒客户端 #46 t=2.00s 被拒客户端 #46 t=3.00s 被拒客户端 #46 t=4.00s 被拒客户端 #46 t=5.00s 被拒客户端 #46 t=6.00s 成功客户端 #47 t=1.00s 被拒客户端 #47 t=2.00s 被拒客户端 #47 t=3.00s 被拒客户端 #47 t=4.00s 被拒客户端 #47 t=5.00s 被拒客户端 #47 t=6.00s 成功客户端 #48 t=1.00s 被拒客户端 #48 t=2.00s 被拒客户端 #48 t=3.00s 被拒客户端 #48 t=4.00s 被拒客户端 #48 t=5.00s 被拒客户端 #48 t=6.00s 成功客户端 #49 t=1.00s 被拒客户端 #49 t=2.00s 被拒客户端 #49 t=3.00s 被拒客户端 #49 t=4.00s 被拒客户端 #49 t=5.00s 被拒客户端 #49 t=6.00s 成功客户端 #50 t=1.00s 被拒客户端 #50 t=2.00s 被拒客户端 #50 t=3.00s 被拒客户端 #50 t=4.00s 被拒客户端 #50 t=5.00s 被拒客户端 #50 t=6.00s 成功0s2s4s6s8s10s
到达冲击:每 0.25s 窗口涌入的请求数(峰值 50 个,容量 10 个/窗)
0容量 1010s
10s 内完成
50/50
最后成功 6.0s
恢复后仍被拒
100
次——扎堆二次雪崩
峰值冲击
50
个/0.25s 窗(容量 10)

固定间隔保护不了任何人:所有人每秒整点同砸,服务恢复后仍被成批拒掉——它自己被重试打满了,永远喘不过气。

调用层的错误分流(本文另一半)
429 / 529 / 超时断流可重试:retryAfter 优先 → 指数退避 → 最多 N 次
529 到顶换 fallback 模型兜底——服务过载谁打都不通;429 只等不换(限的是你自己的配额,换线绕不开)
4xx 参数 / 鉴权不可重试:重试没有意义,立刻抛给人修