Nginx可通过error_page结合try_files、proxy_pass或rewrite实现三级降级:本地文件缺失时内部回源备用站,再失败则返回兜底页;需注意proxy_intercept_errors配置、internal保护及避免循环。

在 Nginx 中,error_page 本身不能直接“跳转到备用源站”,它只能重定向(301/302)或内部重写(location 内部处理)。但结合 try_files、error_page 和 proxy_pass,可以实现静态资源缺失时自动回源到备用服务器,或返回降级页面(如兜底 HTML、占位图、JSON 错误响应等)。关键在于区分“客户端重定向”和“服务端内部回源”两种策略。
方案一:用 error_page + proxy_pass 实现后端降级回源
适用于:主静态资源服务器(如 CDN 或本地 /static)不可用或文件缺失时,由 Nginx 自动向备用源站(如另一台 OSS、对象存储、或 Node 服务)发起请求,对客户端无感。
- 在 server 块中定义主静态 location,并配置
error_page 404 = @fallback - 用
@fallbacknamed location 转发请求到备用源站(需提前配置 upstream 或直连) - 注意:必须关闭
proxy_intercept_errors off(默认为 off),否则 404 不会触发 error_page;若开启,则需配合proxy_next_upstream error timeout http_404做更健壮的上游容错
示例配置:
upstream backup_origin {
server backup.example.com:80;
}
<p>server {
listen 80;
root /var/www/html;</p><pre class="brush:php;toolbar:false;">location /static/ {
# 尝试本地文件,不存在则交由 error_page 处理
try_files $uri @fallback;
}
# 或者显式返回 404 后触发 error_page(更可控)
location ^~ /static/ {
add_header X-Source "primary";
try_files $uri =404;
}
error_page 404 = @fallback;
location @fallback {
add_header X-Source "backup";
proxy_pass https://backup_origin;
proxy_set_header Host backup.example.com;
proxy_set_header X-Real-IP $remote_addr;
# 可选:缓存备用源响应,避免重复穿透
proxy_cache fallback_cache;
proxy_cache_valid 404 1m;
}}
方案二:用 error_page + rewrite 实现前端降级页面
适用于:资源缺失时不回源,而是返回一个预置的降级页面(如 /offline.html、/placeholder.svg、或统一错误页),提升加载稳定性与用户体验。
- 将 404 重定向至本地固定路径(如
error_page 404 /fallback.html) - 确保该路径被 location 捕获并正确返回(推荐用
=精确匹配,避免循环) - 若需保留原始 URI 供前端识别,可用
error_page 404 /fallback.html?uri=$request_uri
示例配置:
error_page 404 /fallback.html;
<p>location = /fallback.html {
internal; # 防止外部直接访问
root /var/www/errors;
add_header Cache-Control "no-store";
}</p><h1>若希望 JS/CSS 缺失时返回空响应或占位内容(如 1x1 gif)</h1><p>location ~* .(js|css|png|jpg|gif)$ {
try_files $uri =404;
}</p><p>error_page 404 /placeholder.gif;</p><p>location = /placeholder.gif {
internal;
alias /var/www/errors/1x1.gif;
}</p>方案三:混合策略 —— 先本地,再备用源,最后降级页
最健壮的生产实践:三级 fallback。例如:本地磁盘 → 备用 HTTP 源站 → 统一兜底页。
- 利用
try_files的多级尝试能力,配合命名 location 和 error_page 衔接 - 注意:try_files 最后一项不能是普通 URI(会变成 301 重定向),应使用
=404或@named触发后续逻辑 - 建议用
internal保护所有兜底 location,防止绕过逻辑直接访问
精简示例:
location /assets/ {
# 1. 本地存在?→ 返回
# 2. 本地不存在?→ 转给 @backup_fetch
# 3. @backup_fetch 返回 404?→ 触发 error_page 到 @degrade
try_files $uri @backup_fetch;
}
<p>location @backup_fetch {
proxy_pass <a href="https://www.php.cn/link/f4abd0461a46858c25c67fba44827f91">https://www.php.cn/link/f4abd0461a46858c25c67fba44827f91</a>;
proxy_intercept_errors on;
error_page 404 = @degrade;
}</p><p>location @degrade {
internal;
root /var/www/errors;
try_files /offline.html =404;
}</p>注意事项与避坑点
实际部署中容易忽略的关键细节:
-
error_page 是“内部重定向”,不改变客户端看到的 URL,除非显式用
302或301(如error_page 404 https://backup.com$uri) -
proxy_intercept_errors 默认为
off,即上游返回 404 时 Nginx 直接透传给客户端,不会触发本层error_page;设为on才能捕获 - try_files 和 error_page 可共存但逻辑不同:try_files 是基于文件系统判断,error_page 是基于 HTTP 状态码拦截;推荐优先用 try_files 做本地检查,error_page 做代理层兜底
-
避免循环:比如 @fallback 又返回 404 并再次触发 @fallback,需用
internal+ 明确的终止条件(如try_files ... =404)控制 -
日志区分来源:通过
add_header X-Source或自定义 log_format 记录走的是哪条路径,便于问题排查










