设为3是生产环境最稳妥的起点,表示首次转发+最多再重试2次;需配合proxy_next_upstream_timeout(建议为proxy_read_timeout的2倍)和健康检查使用,避免重试风暴与无效循环。

设为 3 是生产环境最稳妥的起点,设为 0 或大于 3 反而容易引发重试风暴。
proxy_next_upstream_tries 的计数包含首次请求
它不是“重试次数”,而是“整个请求生命周期内最多尝试转发多少次”。设为 3 表示:首次转发 + 最多再重试 2 次。设为 1 就等于禁用重试(只发一次);设为 0 表示不限次数——这在真实集群中极其危险。
- 当 upstream 中只剩 1 个节点在线,
tries设再大也只会反复打它,形成无效循环 - 默认值是
0,但线上配置必须显式覆盖,不能依赖默认 - 若 upstream 有 2 个节点,
tries 3理论上可能打 A→A→B,也可能打 A→B→B,取决于健康检查状态和随机选择逻辑
必须配合 proxy_next_upstream_timeout 控制总耗时
光限次数没用:proxy_next_upstream_timeout 才是从第一次请求发起开始倒计时的总窗口。比如 proxy_read_timeout 5s,那就建议设 proxy_next_upstream_timeout 为 10s 左右——这样即使前两次都超时(各占 5s),第三次几乎没时间执行,直接失败返回,避免长尾等待。
- 该值不是单次超时,而是全局耗时上限;超过即放弃,不等第三次响应
- 若客户端前端 timeout 是 30s,这里设成 25s 就太激进,容易提前中断可恢复的请求
- 不要把
proxy_next_upstream_timeout设得比proxy_read_timeout还小,否则首次请求就可能被截断
不配健康检查,重试就是往死节点上撞
proxy_next_upstream 是被动容错:等出错了才换人;health_check 是主动筛人:提前把坏节点摘掉。没后者,前者大概率反复打同一台已失联的机器。
- 启用
health_check interval=3 fails=2 passes=2(需 Nginx Plus 或编译了upstream_check_module) - 同时配
max_fails=2 fail_timeout=30s,让短暂抖动不立刻踢节点,但连续失败后能及时隔离 - 若用开源版 Nginx,至少得靠
max_fails/fail_timeout模拟简单探测,不能完全依赖proxy_next_upstream
非幂等请求默认不重试,强行开启风险极高
Nginx 默认只对 GET/HEAD 重试;POST/PUT/DELETE 等方法不会触发 proxy_next_upstream,除非加 non_idempotent 参数——但这要求后端服务 100% 幂等,现实中极难保证。
- 加了
non_idempotent却没做去重、防重放、事务补偿,订单重复、库存多扣、资金误划都是分分钟的事 - 即便业务自称幂等,也要确认是否覆盖所有异常路径(如 DB 写成功但网络断连导致 Nginx 未收到响应)
- 如果必须对 POST 重试,优先考虑前端降级或异步化,而不是依赖 Nginx 层重发
真正容易被忽略的是:重试是否打到了“可用”的节点,而不是仅仅“存在”的节点。只要健康检查滞后、max_fails 阈值松、fails 计数未清空,tries 3 就只是数字游戏。


















