关键是要为重试设定明确边界、节奏和退出条件;应设proxy_next_upstream_tries为3,配合proxy_next_upstream_timeout(如10s)和健康检查,并对非幂等请求慎用重试。

关键不是设多大,而是让重试有边界、有节奏、有退出条件。盲目加大 proxy_next_upstream_tries 容易把流量反复打向已失联或响应极慢的节点,引发“重试风暴”——同一请求在短时间内被多次转发,加重后端压力,甚至拖垮整个集群。
明确重试上限,避免无限循环
proxy_next_upstream_tries 控制的是“整个请求生命周期内最多尝试多少次”,包含首次转发和后续重试。默认值为 0(不限制),这在生产环境非常危险。
- 建议统一设为 3:即最多转发 3 次(1 次原发 + 最多 2 次重试),覆盖单点瞬时故障,又不放大负载
- 设为 1 表示禁用重试(仅首次转发),适合强一致性或非幂等写操作
- 绝对不要设为 0 或过高值(如 10),尤其当 upstream 节点数少于 3 时,极易造成重复打同一台机器
绑定总耗时限制,堵住长尾重试
只限次数不够,必须配合 proxy_next_upstream_timeout 控制整体时间窗口。它不是单次超时,而是从第一次发起请求开始,到最终返回或放弃的总耗时上限。
⚠️ 已弃用 — 该技能已拆分为两个独立技能,以提升模块化程度:**webchat-https-proxy**(HTTPS/WSS 反向代理)和 **webchat-voi...**
- 若
proxy_read_timeout是 5s,建议proxy_next_upstream_timeout设为 8–12s(例如10s) - 这样即使前两次都超时(各 5s),第三次也只剩不到 1s 时间,大概率直接失败并返回错误,而不是继续等待
- 该值应略大于单次合理耗时 × 预期最大重试次数,但不超过客户端可接受的总等待阈值(如前端 timeout 是 30s,这里就不宜设成 25s)
联动健康检查,让重试“打到对的地方”
重试机制本身是被动容错,而健康检查是主动筛人。两者不配合,重试就容易变成“明知山有虎,偏向虎山行”。
- 在 upstream 块中启用探测:
health_check interval=3 fails=2 passes=2;(需 Nginx Plus 或编译了upstream_check_module) - 同时设置
max_fails=2 fail_timeout=30s,让短暂抖动不会立刻踢节点,但连续失败后能及时隔离 - 这样
proxy_next_upstream触发重试时,Nginx 会自动跳过已被标记为“不可用”的节点,真正落到健康的实例上
区分请求类型,非幂等操作慎开重试
GET/HEAD 天然安全可重试;但 POST/PUT/DELETE 等操作一旦重试,可能造成订单重复、库存多扣、状态误翻等严重问题。
- Nginx 默认 不会对非 GET/HEAD 请求重试,哪怕配置了
http_500或timeout - 若业务确认上游完全幂等(极少见),可加
non_idempotent参数显式开启,但务必同步在后端做请求去重(如基于X-Request-ID+ Redis 记录) - 更稳妥的做法:对写接口关闭重试(
proxy_next_upstream off),由前端或业务层控制重试逻辑










