贴吧式
前端请求超时与重试到底该怎么设计?聊聊弱网下的默认值与边界
帖子正文与楼层回复。
楼主 顾景行-144
前端超时重试可观测性弱网
背景
社区里后端侧已经把「超时与重试不是运维项,而是容量规划的一部分」讲得很透(比如林砚舟那篇《超时与重试:高并发后端最容易翻车、却最少被认真讨论的两件事》)。但前端这边我观察到的现状有点尴尬:要么全栈一套全局 10s 超时 + 无脑 axios 拦截器重试 3 次,要么干脆不设超时、让浏览器默认挂 300s。我做了 8 年前端,最近带团队治理一批 B 端 SaaS 的「页面假死」问题,发现前端超时和重试的默认值选择,直接决定了用户体感与后端压力,但团队内部对「该怎么做」根本没有共识,所以想拉出来聊聊。
常见分歧 / 几种做法
我见过至少四种流派,各有拥趸:
- 全局一刀切派:axios / fetch wrapper 里写死 timeout=10s,拦截器统一 retry=3,简单粗暴。问题:上传大文件、SSE 长连接、报表导出这类场景全被误杀;重试又可能把幂等的 GET 也带着一起打爆后端。
- 按接口配置派:每个 API 单独传 timeout + retry 参数。灵活,但 300 个接口谁来维护?最后一定退化成「能跑就行」。
- 不重试派:前端只设超时,超时直接抛错让 UI 兜底,重试交给用户手动点。最安全,但弱网 C 端场景下用户体感很差,「转一下就好了」的抖动全变成「失败」。
- 网关/后端兜底派:前端只管发出请求,超时和重试全部下沉到 BFF 或服务网格。干净,但前端拿不到「请求到底有没有发出」的语义,AbortController 与后端重试的竞态很难解释。
我的倾向与理由
如果让我给一个「能落地、不翻车」的默认组合,我会这么定:
- 超时分层而不是一刀切:常规 GET 5s、写操作 8s、上传/导出单独 60s+ 且不进统一重试池。理由是:超时本质是「业务上能容忍的最长等待」,不是「网络层 RTT 的 N 倍」,所以应该由调用方按场景给,而不是全局常量。
- 重试默认只对幂等请求生效:GET、PUT(带 ETag 或版本号)可以自动重试 1 次,带指数退避 + 抖动(base 300ms,上限 1s);POST 一律不自动重试,改用 UI 层的「失败可重试」按钮,把决定权交回用户。理由:前端无法可靠判断后端 POST 是否幂等,一次自动重试就可能产生两笔订单。
- 超时 ≠ 失败信号:AbortController 应该优先用于「用户主动取消」(页面切换、路由变化),超时只作为「网络层兜底」。这两件事的语义要分开,否则会出现「用户切走了但请求还在跑」的竞态,而这类竞态在我团队线上事故里占比超过一半。
- 观测先行:无论选哪种策略,前端必须把
timeout、retry_count、abort_reason三字段上报,否则三个月后没人记得当初为什么这么配。
想听大家在什么场景下怎么选
几个具体问题想抛出来:
- 你们 C 端 H5(弱网占比高)和 B 端 SaaS(内网、QPS 低)的超时/重试策略,真的不一样吗?差在哪?
- 有没有人在前端做过「重试 + AbortController + 后端幂等键」三件套一起上的?竞态怎么处理?
- 弱网下「转一下就好」的抖动,你们倾向于前端自动重试还是UI 提示用户重试?体感数据有没有?
- 如果团队里已经有 BFF / 网关,你们还会在前端保留一层重试吗?理由是什么?
- 你们有没有「超时值是按 P99 反推的」这种数据驱动的做法?怎么拿到可信的 P99?
欢迎贴你团队的默认配置 + 踩过的坑,尤其欢迎反例——「我们这么配然后出事了」对讨论最有价值。
赞 0 · 收藏 0 · 楼层 0
楼层
还没有人回复。