已采纳
回答正文
回复
讨论正文
该问题的正文与回答。
背景
我在做一个 B 端 SaaS,列表页每 30s 轮询一次聚合接口 /api/summary。后端侧已经按 #23、#1377 那套思路做完了:超时预算、指数退避、熔断都有。但前端侧我们一直是「每个 tab 一份 axios 实例 + 拦截器里失败重试 2 次」,每个 tab 都是独立的——tab A 在退避,tab B 不知道,tab C 还在裸发。
#937 那篇讨论里大家把「客户端该不该熔断」说清楚了,#493 那篇把「弱网 + 无限等待 + 自动重发」翻车讲透了,但**「同一用户 × 多标签页」这个放大维度**我没看到有人正面算过账——这个维度后端是感知不到的(网关只看到 N 个 IP,不知道这 N 个请求是同一个用户),只能靠前端自律。
现象 / 想算的账
假设:在线 5000 用户,人均 2.5 个 tab 开着这个页面,每 30s 轮询 1 次。后端某晚 P99 从 200ms 抖到 4s(没崩,只是慢),前端超时阈值 3s,重试 2 次、退避 base 500ms 指数递增。
这个 2.2× 是我手算的,没考虑退避错峰(指数退避会让重试时间错开,但多 tab 之间退避起点不同,错峰效果其实打折)。
已尝试的排查与结果
sessionStorage 存一个「最近 N 秒内该接口失败次数」,tab 之间共享——失败:sessionStorage 是同源共享的,看起来能用,但实测发现 tab A 写 tab B 读不到实时值,只有 storage 事件触发后才同步,弱网下事件派发延迟 100–300ms,挡不住「两个 tab 同时首发」的窗口。BroadcastChannel 做跨 tab 的「冷却期」广播——能用,但只挡「首发」:tab A 失败后广播「冷却 5s」,tab B 收到后 5s 内不发。但退避起点仍然各自独立:tab A 第 1 次重试在 500ms,tab B 第 1 次重试在 800ms(因为它 300ms 才失败),退避曲线还是错开的,放大系数只从 2.2× 降到 1.8× 左右,没根治。Retry-After 头,前端按这个头退避——只能挡「同 tab」,跨 tab 还是要前端自己协调。期望得到的答案形态
localStorage 存一个「该接口下一次可发时间戳」,所有 tab 读同一个值来错峰?)有没有真实项目这么做过、踩过什么坑?我倾向的方案是「localStorage 存冷却时间戳 + BroadcastChannel 广播失败事件」,但没在真实项目里压测过,想听听有没有人做过、踩过什么坑。
欢迎带真实场景和数字来聊,别只聊原则。