nginx通过proxy_read_timeout将后端响应慢转化为timeout错误,再由proxy_next_upstream error timeout http_504触发重试;需配合proxy_next_upstream_tries、proxy_next_upstream_timeout及多节点upstream配置实现可控故障转移。

要让 Nginx 在后端响应缓慢时自动中断当前请求并转向其他节点重试,关键不是“感知慢”,而是把“慢”转化为 Nginx 能识别的明确失败事件——最常用、最可控的方式是用 proxy_read_timeout 触发 timeout 错误,再由 proxy_next_upstream 启动重试。
把“慢”变成“超时”:核心靠 proxy_read_timeout
Nginx 不会因为后端花了 8 秒还没返回数据就判定为“慢”并重试。它只在等待响应头的过程中超过设定阈值时,才主动断开连接并标记为 timeout。这个阈值就是 proxy_read_timeout。
- 设为 8s 或 10s:适合多数业务接口,既避免误判正常慢查询,又防止用户长时间白屏
- 一旦后端在此时间内未发送状态行和响应头(比如卡在数据库锁、网络抖动、GC 暂停),Nginx 就中断本次连接
- 此时触发的是 timeout 类错误,而非 200 响应——这是重试能生效的前提
显式启用 timeout 重试:proxy_next_upstream 必须包含 timeout
默认情况下,Nginx 只对 error 和 timeout 重试,但很多配置会覆盖默认值。务必显式写出:
- proxy_next_upstream error timeout:覆盖连接失败 + 响应头超时两类基础场景
- 补充 http_504:有些后端在自身超时后主动返回 504,这时 timeout 不触发,但 http_504 可以接上
- 推荐组合:error timeout http_504——覆盖 Nginx 自身超时、后端自报超时、连接异常三类典型“慢导致失败”情形
控制重试边界:防雪崩的关键参数
光有触发条件不够,必须限制次数和总耗时,否则可能把压力全打到下一个节点:
- proxy_next_upstream_tries 3:最多尝试 3 次(首次 + 最多 2 次重试),避免无限转发
- proxy_next_upstream_timeout 25s:从第一次请求发出起计时,整套流程不能超过该时间;建议 ≥ proxy_read_timeout × 2.5,留出网络与调度余量
- 单次超时参数也要协同:proxy_connect_timeout 3s、proxy_send_timeout 5s,保持各阶段节奏一致
依赖多节点与健康检查:重试生效的前提
重试不是“重发给同一台”,而是“换一台”。没有备用节点,所有配置都无效:
- upstream 至少定义 2 台 server,例如:server 10.0.1.10:8080 max_fails=3 fail_timeout=30s;
- max_fails/fail_timeout 启用被动健康检查:某节点连续失败 3 次,30 秒内不再参与调度,提升重试成功率
- 可加 backup 节点作兜底,但不建议作为主力重试目标











