状态码本身不决定容错,而是通过proxy_next_upstream、error_page和upstream分组分类触发重试、降级或兜底:503/504可安全重试,500需谨慎,400/404禁止重试;须显式配置http_503等触发条件,并配合tries、timeout及健康检查形成闭环。

状态码本身不决定容错,而是你用它来触发 Nginx 的容错动作。关键不是“根据状态码做容错”,而是把不同状态码归类后,分别交给 proxy_next_upstream、error_page 和 upstream 分组去执行对应策略:重试、降级、兜底或拦截返回。
区分三类错误再配置重试
盲目对所有 5xx 重试会放大问题,必须按语义分类:
- 可安全重试:503(服务暂时不可用)、504(网关超时)——通常是瞬时过载或网络抖动,换节点成功率高
- 需谨慎重试:500(内部错误)、502(网关错误)——可能是代码异常或 DB 故障,仅当确认多活部署且其他节点健康时才启用
- 禁止重试:400(参数错误)、404(资源不存在)——问题在客户端,重试只会增加无效负载
显式配置 proxy_next_upstream 触发条件
默认只响应 error 和 timeout,HTTP 状态码不会自动触发重试。必须手动列出:
- 最小安全集:
proxy_next_upstream error timeout http_503 http_504; - 若支持 500 重试,加
http_500,但要确保后端具备多活能力 - 避免写
http_404,除非你有镜像源或静态 fallback 页面 - 注意:
proxy_next_upstream只在请求尚未向客户端发送响应体时生效
用 error_page 实现状态码拦截与转换
仅靠重试不够,还要控制最终返回给用户的内容:
- 开启拦截开关:
proxy_intercept_errors on;(必须放在location块内) - 定义跳转规则,例如:
error_page 502 504 /maintenance.html; - 路径需匹配
location = /maintenance.html,并设internal;防套娃 - 可做语义转换,比如把上游 500 统一转为 503:
error_page 500 =503 @handle_500;
结合 upstream 分组实现差异化兜底
单一 upstream 无法表达“503 走备用组、500 返回 JSON”的意图,需配合命名 location:
- 定义主组:
upstream origin_primary { server a:8080 max_fails=2 fail_timeout=30s; } - 定义专用备用组:
upstream origin_backup_5xx { server b:8080 backup; } - 在 location 中拦截并跳转:
error_page 503 504 = @retry_5xx;,再配location @retry_5xx { proxy_pass http://origin_backup_5xx; } - 失败后还可接缓存兜底或降级接口,比如返回本地静态 JSON 或 CDN 缓存











