nginx 在后端全挂时需通过 proxy_intercept_errors on、error_page 映射至 maintenance.html、upstream 容错三者协同,实现友好降级页面;须确保页面≥512字节、路径正确、mime明确,并可选统一状态码或注入动态信息。

当后端服务全部挂掉时,Nginx 默认返回简陋的 502 Bad Gateway 页面,用户体验差,还可能触发告警风暴。要显示友好的错误提示页(如维护页),关键不是“拦截失败”,而是让 Nginx 在所有重试都失败后,主动接管并返回一个可读、可控的降级页面。这需要三方面协同:拦截开关、错误映射、容错策略。
必须开启 proxy_intercept_errors on
这个指令默认是关闭的,不启用就完全不会接管后端返回的 4xx/5xx 响应(包括 Nginx 自己生成的 502/503/504)。
它必须放在 location 块内(而不是 http 或 server 级),避免影响静态资源等非代理路径:
location / {
proxy_pass http://backend;
proxy_intercept_errors on; # 关键:只在此 location 生效
}
注意:如果是 FastCGI(如 PHP),则用 fastcgi_intercept_errors on;;反向代理场景只认 proxy_intercept_errors。
显式配置 error_page 并确保页面可访问
仅开开关不够,必须配对 error_page,且目标页面路径要真实存在、权限正确、MIME 类型明确:
error_page 500 502 503 504 /maintenance.html;
location = /maintenance.html {
internal; # 防止用户直接访问该 URL
root /usr/share/nginx/html; # 文件实际位置:/usr/share/nginx/html/maintenance.html
types { text/html html; } # 确保浏览器渲染为 HTML,而非下载
}
⚠️ 注意事项:
- 文件大小不能小于 512 字节(IE 和部分旧客户端强制要求),可用
wc -c /path/to/maintenance.html检查; - 页面中引用的图片、CSS 等资源,需确保对应
location可访问(例如/img/要有独立location /img/配置); - 不要用
alias替代root,容易路径拼接错误;root后不带结尾斜杠,Nginx 自动拼/maintenance.html。
配合 upstream 容错,避免“惊群响应”
后端全挂时,若不设限,每个请求都会立即尝试连接并返回 502,造成日志爆炸。应缩短超时、启用节点剔除、合理重试:
upstream backend {
server 10.0.0.1:8080 max_fails=1 fail_timeout=30s;
server 10.0.0.2:8080 max_fails=1 fail_timeout=30s;
proxy_next_upstream error timeout http_502 http_503 http_504;
}
location / {
proxy_pass http://backend;
proxy_connect_timeout 3s;
proxy_read_timeout 10s;
proxy_intercept_errors on;
error_page 500 502 503 504 /maintenance.html;
}
这样逻辑更清晰:先尝试所有后端(带重试),全部失败后才由 Nginx 生成最终错误响应,此时 error_page 才真正触发。
在无 root/sudo 权限的环境(云容器、VPS、隔离主机)中安装并配置 OpenClaw 浏览器工具的 headless Chrome。适用场景:...
可选:隐藏原始状态码或注入动态信息
如果前端不依赖具体错误码(如纯展示),可把状态码统一改为 200,提升缓存友好性:
error_page 502 =200 /maintenance.html;
若需保留原始状态码(如前端 JS 做差异化处理),务必写成 =502:
error_page 502 =502 /maintenance.html;
还可配合 $status 变量注入当前错误码到页面中(需开启 ssi on 或用 Lua):
location = /maintenance.html {
internal;
root /usr/share/nginx/html;
ssi on;
}
然后在 maintenance.html 中写 <!--# echo var="status" -->。
验证是否生效:停掉所有后端服务,执行 curl -v https://your-domain/,观察是否返回 200(或你设定的状态码)及自定义页面内容,并检查响应头是否有 X-Handled-By: nginx-error-page(可加 add_header 辅助确认)。










