关键是要为重试设定硬性红线:单次请求最多转发次数、总耗时上限、目标节点三者缺一不可;设错 proxy_next_upstream_tries 不仅防不住雪崩,反而加速崩溃。

关键不是“多试几次更稳”,而是给重试划一条硬性红线:单次请求最多转发几次、总耗时多久、打给谁——三者缺一不可。设错 proxy_next_upstream_tries 不仅防不住雪崩,反而会加速崩溃。
明确 tries 是总次数,不是额外重试次数
设为 3 表示:第 1 次发给原始节点 + 最多再换节点重试 2 次,整个生命周期最多 3 次请求。不是“失败后再试 3 次”。
- 设为 0(Nginx 默认)= 无限重试,生产环境必须覆盖,极其危险
- 设为 1 = 禁用重试,适合订单提交、支付回调等非幂等操作
- 设为 3 = 平衡容错与安全,覆盖网络抖动、瞬时超时等常见故障
- 设为 ≥5,尤其 upstream 节点少于 3 台时,极易反复打同一台已失联或假死机器
必须绑定 proxy\_next\_upstream\_timeout 控制总耗时
proxy_next_upstream_timeout 是从第一次请求发出开始计时的总窗口,超时立即终止所有尝试并返回错误。只控次数不管时间,等于纵容长尾请求。
- 若单次合理响应约 3 秒,tries 3 时建议 timeout 设为 8–10 秒(留出调度与网络余量)
- 若 proxy_read_timeout 是 5 秒,timeout 不宜超过 12 秒,否则第三次尝试可能只剩不到 1 秒,大概率直接失败
- 单独设 tries 5 但 timeout 30s,前两次各耗 15 秒,第三次根本没机会执行
只对真正可恢复的错误触发重试
重试不是兜底万能键,加错状态码会把业务异常也复制放大。
- 最小安全集:proxy_next_upstream error timeout(只对连接失败、超时重试)
- 确认上游幂等且稳定后,可谨慎加 http_502 http_503 http_504
- 绝对不要加 http_404、http_403、http_500——它们多属客户端错误或业务异常,重试无意义,还可能重复扣款、生成重复订单
- POST/PUT/DELETE 默认不重试;强行加 non_idempotent 必须由业务层 100% 保障幂等(如唯一 request_id + Redis 去重)
健康检查不能缺位,否则重试只是空转
proxy_next_upstream 是被动兜底,health_check 才是主动防御。没有它,Nginx 会不断把请求发给已失联或假死的节点。
- 在 upstream 块中启用主动探测:health_check interval=3 fails=2 passes=2;
- check_http_expect_alive 只认 2xx/3xx,避免把返回 200 的空 /health 接口当真
- 配合被动策略:max_fails=2 fail_timeout=30s,让偶发失败也能快速下线节点
- fail_timeout 别设过长(如 60s),否则节点已挂却还要参与转发十几秒











