真正优雅的降级容灾应以 try_files 为主干路径试探,配合 error_page + 命名 location 分层接管失败,rewrite 仅用于命名 location 内轻量路径微调(如补斜杠、清参),不参与主干容错逻辑。

直接用 rewrite 和 try_files 混合处理降级容灾,通常不是好做法——两者逻辑冲突、执行顺序难控,容易引发循环重写或意外跳转。真正优雅的降级容灾,核心是用 try_files 做路径试探主线,靠 error_page + 命名 location 分层接管失败,rewrite 只在极少数必要环节做轻量路径修正(比如统一补斜杠、清理冗余参数),不参与主干容错流程。
别让 rewrite 干 try_files 的活
rewrite 是重写 URI 后触发新匹配,可能多次跳转、绕过缓存、干扰日志;try_files 是内部按序检查,零重定向、低开销、语义明确。降级要的是“一次请求、多级兜底”,不是“反复改地址再找”。例如下面这种写法危险:
-
rewrite ^/api/(.*)$ /v1/$1 break;→ 再配try_files $uri @fallback;:URI 被改过,$uri 已不是原始值,缓存和 fallback 路径全乱 - 多个
rewrite嵌套 +if判断:Nginx 官方明确不推荐,易出边界问题,调试困难
用 try_files 主线 + error_page 分流构建容错链
把静态资源、本地缓存、主服务、备服务、兜底响应串成一条可预测的 fallback 链,每个环节只做一件事:
-
try_files /cache$uri /static$uri @primary;:先查缓存目录,再查静态目录,都不成就跳命名 location -
location @primary { proxy_pass http://upstream-main; proxy_intercept_errors on; error_page 502 503 504 = @backup; }:主代理失败时,不返回错误页,而是静默切到备节点 -
location @backup { proxy_pass http://upstream-backup; proxy_intercept_errors on; error_page 502 503 504 = @degrade; }:备用也挂了,进兜底 -
location @degrade { try_files /degrade/maint.html =503; }:返回维护页,或直接return 503 "Service degraded";
rewrite 只在必要处做“微调”,不介入主流程
如果确实需要路径转换,限制在命名 location 内部、且仅用于适配后端接口格式,不改变容错逻辑:
- 主代理前统一加版本前缀:
location @primary { rewrite ^/(.*)$ /v2/$1 break; proxy_pass http://backend; } - 清理多余查询参数避免缓存污染:
location @primary { set $args ""; proxy_pass http://backend; }(比 rewrite 更轻量) - 强制目录结尾补
/(配合index):location /blog { if (-d $request_filename) { rewrite ^/(.*[^/])$ /$1/ permanent; } }—— 这类只影响 SEO 或用户体验,不影响降级路径
SPA 应用的典型降级配置(含轻量 rewrite 辅助)
Vue/React 项目既要支持 history 路由,又要保障 API 失败时前端能展示友好提示:
-
location / { try_files $uri $uri/ /index.html; }:确保所有页面路由回退到 index.html -
location /api/ { try_files @cache @primary; }:API 请求不走文件系统,直连代理层 -
location @cache { internal; try_files /var/cache/api$uri.json =404; }:内部 location,仅供 try_files 调用,不对外暴露 -
location @primary { proxy_pass https://api.example.com; proxy_set_header X-Forwarded-For $remote_addr; }:主 API,失败由上层error_page捕获 - 前端 JS 检测
window.location.pathname === '/degraded'时自动加载降级 UI,后端只需在兜底 location 返回该路径即可


















