Nginx可通过error_page指令统一管理404/50x错误响应,支持静态页、动态重定向及日志标记;结合$upstream_status等变量区分错误来源,按API/Web路径返回JSON或HTML,并通过Git托管错误页、添加Cache-Control头、注入上下文信息、增强日志与告警实现可观测性。

在 Nginx 作为 API 网关或前端入口的场景下,统一管理错误页面(尤其是 404 和 50x)不仅能提升用户体验,还能增强系统可观测性与品牌一致性。关键在于:不依赖后端应用各自处理,而是由 Nginx 在最外层拦截、识别并响应错误,同时支持静态定制页、动态重定向或日志标记。
配置 error_page 指令接管错误响应
Nginx 默认会返回简陋的内置错误页。要启用自定义逻辑,需在 http、server 或 location 块中使用 error_page 指令显式声明拦截规则:
- 用
error_page 404 /404.html;将所有 404 响应重写为返回指定静态文件(路径相对于root或alias) - 支持多状态合并:
error_page 500 502 503 504 /5xx.html; - 若需保留原始状态码(如避免 502 被转成 200),添加
=前缀:error_page 502 =502 /gateway-error.html; - 可配合
try_files实现 fallback 逻辑,例如:error_page 404 @fallback;+location @fallback { try_files /static/404.html =404; }
区分错误来源:网关层 vs 后端服务
单纯返回静态页不够智能。建议通过变量识别错误根因,实现差异化响应:
- 用
$upstream_status判断是上游超时(504)、连接失败(502)还是后端返回了 500 —— 可据此返回不同提示文案或重试引导 - 用
$request_uri和$host记录未匹配路由的请求,便于排查配置遗漏或恶意扫描 - 对 API 路径(如
/api/开头)返回 JSON 错误体:error_page 404 =404 /api-404.json;,内容为{"code":404,"message":"Endpoint not found"} - 对 Web 页面路径返回 HTML 页,并内嵌 JS 自动上报错误类型到监控平台
统一错误页托管与版本控制
避免在每台 Nginx 机器上手动更新 HTML 文件。推荐做法:
- 将所有错误页(404.html、50x.html、api-404.json 等)放在独立 Git 仓库,构建后同步至统一静态资源目录(如
/var/www/errors/) - 在 Nginx 配置中用
alias /var/www/errors/;指向该目录,确保所有error_page引用路径一致 - 添加 HTTP 头防止缓存干扰调试:
location ~ ^/(404|5[0-9]{2})\.html$ { add_header Cache-Control "no-cache, no-store, must-revalidate"; } - 支持简单变量注入:用 Lua 模块(如
ngx.var)或 NJS 在响应前动态插入时间、网关节点名等上下文信息
记录与告警:让错误可见可追溯
错误页不只是“展示”,更是诊断入口:
- 在
log_format中加入$upstream_status、$upstream_addr、$request_time,区分真实业务失败和网关自身异常 - 对高频 404(如每分钟超 10 次)配置 access_log 的条件记录:
access_log /var/log/nginx/error_404.log if=$log_404;,配合 map 定义 $log_404 - 用
return+log_not_found off避免无效日志刷屏;对明确拒绝的路径(如/wp-admin)直接return 403并单独打点 - 将错误页访问本身作为健康信号:Prometheus 抓取
nginx_http_request_total{code=~"404|5.."},设置突增告警
不复杂但容易忽略:Nginx 的 error_page 是内部重定向,不会触发外部跳转,因此浏览器地址栏不变;若需跳转,改用 return 302 或 rewrite ... permanent。真正生效前务必测试 reload 后的配置语法(nginx -t)并验证响应头与状态码是否符合预期。

















