nginx高可用重试需四维协同:精准定义可重试错误(timeout、502/503/504)、限制tries与timeout、结合主被动健康检查剔除坏节点、按http方法语义控制重试(仅get/head默认安全)。

解决 Nginx 高可用环境下的网络连接重试频率问题,关键在于避免无效重试放大压力,同时保障真正可恢复的失败请求得到合理兜底。这不是调大或调小某个数字就能解决的事,而是要从触发条件、次数控制、节点状态感知和请求语义四个维度协同约束。
精准定义哪些错误才允许重试
默认 proxy_next_upstream error 过于保守,仅覆盖连接失败;但盲目加入所有 5xx 也不合适。应按实际故障类型分级处理:
- 必须包含:timeout(响应慢)、http_502 / http_503 / http_504(网关层异常),这些大概率是瞬时抖动或上游临时不可用
- 明确排除:http_400、http_404、http_403 —— 这些是业务逻辑错误,重试只会重复错误路径
- 谨慎对待:http_500 —— 若由后端程序崩溃导致,可重试;若由参数校验失败引发,则不应重试
严格限制单次请求的总尝试次数与耗时
proxy_next_upstream_tries 表示“最多转发几次”(含首次),不是“额外重试几次”。设为 3 意味着最多打 3 个节点,而非重试 2 次后再加原请求。
- 高并发场景下,tries ≥ 4 且 upstream 节点少于 3 台时,极易反复打同一台已失联机器
- 必须绑定 proxy_next_upstream_timeout 控制整体窗口,例如:
— 若单次正常响应在 2–4 秒,timeout 建议设为 6–10 秒
— timeout=30s + tries=3 ≠ 更可靠,反而可能让前两次各卡 12 秒,第三次根本没机会执行
让重试前先剔除坏节点,而不是边重试边撞墙
没有健康检查的重试,就像蒙眼换车道——你不知道下一个是不是坑。被动重试必须搭配主动探测:
- 在 upstream 块中启用 health_check interval=3 fails=2 passes=2,3 秒一次心跳,连续 2 次失败即摘除
- 同时保留被动机制:max_fails=2 fail_timeout=30s,双保险应对突发闪断
- 避免 health_check 间隔超过 10 秒,或 fails 设为 5 以上,否则宕机节点可能滞留数分钟
按请求方法决定是否开启重试能力
重试不是万能胶,而是带风险的操作放大器。不同 HTTP 方法语义差异极大:
- GET / HEAD 类查询:天然幂等,可安全启用重试
- POST / PUT / DELETE:默认禁止重试。如确需(如日志上报),必须由后端 100% 实现幂等(如透传 idempotency key + 服务端去重)
- Nginx 不会自动对非 GET/HEAD 请求重试,除非显式关闭 buffering 并启用 non_idempotent —— 生产环境不建议手动开启











