Nginx可通过proxy_intercept_errors + error_page + 命名location return实现上游全熔断时返回自定义JSON降级响应;需同时满足开启错误拦截、精准绑定502/503/504至内部location、在internal命名location中用单引号return JSON并显式设置Content-Type UTF-8。

要让 Nginx 在 upstream 熔断(即所有后端被标记为 down)时,不转发、不报错,而是直接返回一个标准化的 JSON 降级响应(如 {"code":503,"msg":"服务暂时不可用"}),关键在于:**绕过代理转发逻辑,用 error_page 拦截上游失败状态,并由命名 location 用 return 原生输出 JSON**。整个过程不依赖 Lua、不调用后端,毫秒级生效。
配置核心三步走
必须同时满足以下三点,缺一不可:
-
开启错误拦截:在
location块中添加proxy_intercept_errors on;,否则 Nginx 会直接把 502/503 等原样透传给客户端,无法触发error_page -
精准绑定错误码:用
error_page 502 503 504 = @fallback;(注意等号=表示内部重定向且保持状态码;若想统一返回 200,写成=200 @fallback) -
命名 location 返回 JSON:定义
location @fallback { internal; default_type application/json; add_header Content-Type 'application/json; charset=utf-8'; return 200 '{"code":503,"msg":"服务暂时不可用"}'; }
完整可运行示例
以下配置放在 server 块内即可生效:
upstream order_backend {
server 192.168.1.10:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.11:8080 max_fails=3 fail_timeout=30s;
}
<p>location /api/order {
proxy_pass <a href="https://www.php.cn/link/ac68bc93ecc07d7daec8ce924ca09b0c">https://www.php.cn/link/ac68bc93ecc07d7daec8ce924ca09b0c</a>;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;</p><pre class="brush:php;toolbar:false;">proxy_intercept_errors on;
error_page 502 503 504 = @order_fallback;
# 可选:提升熔断灵敏度(见下文说明)
proxy_next_upstream error timeout http_502 http_503 http_504;
proxy_next_upstream_timeout 5s;}
location @order_fallback { internal; default_type application/json; add_header Content-Type 'application/json; charset=utf-8'; return 200 '{"code":503,"msg":"订单服务暂不可用,请稍后再试","trace_id":"'$request_id'"}'; }
说明:$request_id 是 Nginx 内置变量(需在 http 块启用 log_format 或 map 定义),可用于问题追踪;JSON 字符串必须用单引号包裹,且不能换行。
为什么 upstream 全 down 后还会触发 503?
Nginx 在所有 upstream 节点都处于 down 状态时,proxy_pass 会立即返回 503(Service Temporarily Unavailable)。这不是后端返回的,而是 Nginx 自身的兜底行为。所以只要配置了上述 error_page + proxy_intercept_errors,就能捕获这个 503 并替换为自定义 JSON。
增强可靠性的小技巧
-
避免 fallback 被外部访问:务必加
internal;,防止用户直接请求/@order_fallback触发响应 -
中文不乱码:仅靠
default_type application/json不够,必须用add_header Content-Type 'application/json; charset=utf-8'显式声明编码 -
区分业务错误与熔断:若后端主动返回 503(如限流),可通过
proxy_hide_header隐藏原始响应头,确保只由 Nginx 控制降级逻辑 -
加 backup 节点不冲突:即使你配置了
server ... backup;,只要主节点未全 down,就不会走到 fallback;只有 backup 也失败或未配置时,才真正触发此处 JSON 降级











