nginx 不自动重试不同后端,但通过 proxy_next_upstream、upstream 健康状态管理及分层超时参数可实现生产级容错降级;关键在于明确重试条件、终止时机与失败兜底策略。

直接说结论:Nginx 本身不自动重试“不同后端”,但通过 proxy_next_upstream + upstream 健康状态管理 + 合理超时参数组合,能实现生产级的后端容错与降级能力。关键不是“有没有重试”,而是“重试什么、何时停、失败后怎么办”。
proxy_next_upstream 控制重试触发条件
这个指令决定 Nginx 在什么错误下把请求甩给下一个 upstream server,但它只在响应未发回客户端前生效(即没写响应体之前)。默认它不包含任何 HTTP 状态码,必须显式声明。
- 常见有效组合:
proxy_next_upstream error timeout http_500 http_502 http_503 http_504—— 覆盖连接失败、超时、源站崩溃类错误 - 慎加
http_404:除非你确认多个源站数据完全镜像(如 CDN 多活源),否则 404 是业务确定性结果,重试只会放大负载 - 避免
non_idempotent:对 POST/PUT 等非幂等请求开启该选项会导致重复提交,极难排查 - 不要写
proxy_next_upstream on:该值已废弃,Nginx 1.21+ 会报配置警告
proxy_*_timeout 必须分层设置,不能一锅炖
超时不是设一个数就完事。Nginx 请求生命周期中每个阶段都有独立瓶颈,混用会导致误判或掩盖问题。
-
proxy_connect_timeout:建议 1–3s。这是建 TCP 连接的时间,设太长会让故障节点拖慢整个 upstream 组调度 -
proxy_send_timeout:建议 5–15s。控制 Nginx 向后端发完整请求(含 body)的耗时,适用于大文件上传或流式请求 -
proxy_read_timeout:通常最长,建议 15–60s。它从发完请求开始计时,等待后端返回第一个字节 —— 直接关联后端处理逻辑耗时 - 注意:
proxy_next_upstream_timeout是总重试窗口(含首次请求),不是单次超时;设为 10s 比设 30s 更利于防长尾
upstream 节点健康状态靠 max_fails/fail_timeout 被动维持
Nginx 开源版没有主动探测,靠真实请求失败来“学习”节点是否可用。这机制简单但足够可靠,前提是参数不瞎配。
-
max_fails=2 fail_timeout=30s是较稳的起点:连续 2 次失败后,该节点 30 秒内不参与调度 -
fail_timeout应 ≥ 2×proxy_read_timeout:防止后端偶发抖动(如 GC)被立即摘除 - 务必配
backup节点:当所有主节点都被标记为不可用时,backup才会被启用,它是兜底的最后一道闸 - 权重(
weight)不影响健康检查逻辑,只影响正常流量分配比例
error_page + proxy_cache_use_stale 是真正的降级开关
当所有 upstream(含 backup)都失败,proxy_next_upstream 已无路可走,此时要避免返回裸 502/503,而是用缓存或静态页兜底。
-
error_page 502 503 504 /fallback.html;:指向本地文件,秒级生效,不依赖后端 -
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;:允许在后端异常时,返回陈旧缓存(stale),用户无感 - 搭配
proxy_cache_lock on;可防缓存击穿,但会轻微增加延迟,需权衡
真正容易被忽略的是:重试和健康检查共同作用时,proxy_next_upstream 决定“这次要不要换人”,而 max_fails 决定“下次还让不让这个人干活”。两者时间尺度不同、触发路径不同,必须分开调优,不能指望一个配置解决所有问题。











