Nginx差异化重试需组合proxy_next_upstream、多upstream分组与error_page:仅对503/504等临时性错误重试,慎用500,禁用404;通过命名upstream分组和error_page跳转实现按错误类型分流;失败时用error_page转换状态码或返回缓存。

要让 Nginx 对不同后端错误状态码执行差异化重试,核心是组合使用 proxy_next_upstream、upstream 分组策略与 error_page 降级逻辑,而不是对所有 5xx 统一处理。关键在于区分“可重试错误”和“不可重试错误”,并为每类设定明确边界。
精准控制哪些状态码触发重试
proxy_next_upstream 默认不响应 5xx,必须显式声明。但不能无差别加所有 5xx —— 比如 500 可能是业务逻辑崩溃,重试未必有效;而 503 很可能是源站临时过载,换节点成功率高。
- 推荐最小集:
proxy_next_upstream error timeout http_503 http_504;—— 聚焦网络层与临时性服务不可用 - 谨慎加入
http_500:仅当确认源站 500 是瞬时资源争用(如 DB 连接池满)且多活部署下其他节点大概率可用时才启用 - 避免
http_404:除非你有镜像源或静态 fallback,否则 404 是确定性结果,重试只会放大无效流量
用 upstream 分组实现按错误类型分流重试
单一 upstream 无法区分重试意图。可定义多个 upstream 块,按语义命名,并在 location 中动态选择:
- 主源组:
upstream origin_primary { server a.example.com max_fails=2 fail_timeout=30s; } - 只响应 503/504 的备用组:
upstream origin_backup_5xx { server b.example.com backup; } - 在 location 中结合 error_page 触发切换:
error_page 503 504 = @retry_5xx;<br> location @retry_5xx { proxy_pass http://origin_backup_5xx; }
用 error_page + return 实现状态码语义转换与兜底
当重试失败或明确不重试时,可将原始错误转化为更准确的状态码,或返回结构化响应:
- 把上游 500 转为 503 并返回 JSON:
error_page 500 =503 @handle_500;<br> location @handle_500 { default_type application/json; return 503 '{"code":"SERVICE_UNAVAILABLE"}'; } - 对特定路径的 503 直接返回缓存旧内容:
error_page 503 = @stale_fallback;<br> location @stale_fallback { proxy_cache_use_stale error timeout updating; proxy_pass http://origin_primary; }
验证与调优要点
重试是否生效不能只看日志是否有报错,要关注实际行为:
- 开启
log_format记录$upstream_addr和$upstream_status,确认请求是否真的轮转到下一个 server - 设置
proxy_next_upstream_tries 2和proxy_next_upstream_timeout 10s防止无限重试拖垮边缘节点 - 若后端支持健康检查,配合
health_check interval=5 fails=2 passes=2,让 Nginx 主动剔除异常节点,比被动重试更高效


















