要全面拦截5xx错误,需显式配置http_502/503/504并谨慎启用http_500,禁用4xx类状态码;配合proxy_next_upstream_tries 3、timeout 6s及upstream健康检查max_fails=3 fail_timeout=30s,并启用proxy_intercept_errors与error_page兜底。

要让 proxy_next_upstream 真正全面拦截并容错后端集群返回的 5xx 错误,不能只加 http_500 到配置里——Nginx 默认不把任何 HTTP 状态码当作可重试条件,必须显式声明、精准筛选、严格限流,并与健康检查联动,否则要么漏判,要么雪崩。
只对真正适合重试的 5xx 类型启用
不是所有 5xx 都该重试:
-
推荐加入:
http_502(网关错误,常见于后端进程闪退或连接重置)、http_503(服务过载或主动熔断)、http_504(上游响应超时),这三类大概率是瞬时故障,换节点成功率高 -
谨慎加入:
http_500—— 仅当确认是偶发性底层异常(如 JVM GC 暂停、临时磁盘满)且业务日志已验证幂等性时才启用;若 500 来自空指针或 SQL 死锁,重试只会放大问题 -
禁止加入:
http_404、http_403、http_429等客户端类状态码,它们是确定性业务结果,重试等于制造无效流量
必须搭配 tries 和 timeout 双重约束
没有边界的重试等于放弃控制:
-
proxy_next_upstream_tries 3:表示最多尝试 3 个不同节点(含首次请求),不是“重试 3 次”。设为 3 时,实际最多换 2 台新节点 -
proxy_next_upstream_timeout 6s:从第一次请求发出开始计时,6 秒内无论试了几台,超时即返回 502。它必须小于proxy_read_timeout(例如后者设为 10s,前者建议 6–8s) - 避免设
tries 0或不设timeout—— 这会导致单次请求卡住所有后端,P99 延迟飙升
让失败真正触发节点摘除,而非反复试探
光重试不摘节点,等于每次请求都先打坏一次:
- 在
upstream块中为每个 server 明确配置:max_fails=3 fail_timeout=30s - 关键前提:这些失败必须被计入——所以
proxy_next_upstream必须包含对应错误类型(比如写了http_502,502 才会累加max_fails) - 连续 3 次因 502/503/timeout 等触发重试失败后,该节点自动隔离 30 秒;超时后首个请求会试探性转发,成功则恢复,失败则重置计数
补充拦截兜底,防止用户看到原始 5xx
重试失败后,别直接透传错误给用户:
-
proxy_intercept_errors on;:开启 Nginx 拦截后端返回的 4xx/5xx 响应 -
error_page 502 503 504 = @fallback;:将拦截到的网关类错误导向降级逻辑 - @fallback 可指向静态 HTML 页、兜底 API 接口,或返回预设 JSON(如
{"code":503,"msg":"服务暂不可用"}),同时保留原始日志供排查











