try_files 是 Nginx 实现多级缓存降级的核心指令,通过按序检查真实文件路径实现“命中即返、否则继续”:优先静态缓存文件(如 /data/cache/$host$uri/index.html),再 fallback 至后端(@php 或 @origin)。

Try_files 是 Nginx 中实现“按顺序尝试多个路径/资源,命中即返回,否则继续”的核心指令,非常适合构建多级缓存降级策略:比如先查本地内存缓存(如 fastcgi_cache / proxy_cache 的缓存文件),再查磁盘静态缓存(如预生成的 HTML 文件),最后回源到后端应用。关键在于把缓存产物映射为可被 try_files 检查的**真实文件路径**。
1. 明确缓存层级与对应文件路径
多级降级的前提是每一级缓存都落盘为 Nginx 能直接 stat() 的文件(或能通过内部重定向访问)。常见三级结构:
-
Level 1(最快):Nginx 内置缓存(
proxy_cache或fastcgi_cache)——但它不暴露文件路径,try_files无法直接检查。需配合proxy_cache_use_stale或用map+error_page间接触发,不能直接用于 try_files。 -
Level 2(推荐主力):预生成静态文件(如
/cache/$host/$uri/index.html),由后端定时或事件触发生成。这是try_files最自然、最可控的一层。 -
Level 3(兜底):动态回源(如
proxy_pass http://backend),通常用命名 location 或内部重定向实现。
2. 使用 try_files 实现两级静态缓存降级(最常用)
假设你将页面缓存为 /data/cache/example.com/about/index.html,并希望未命中时交由 PHP-FPM 处理:
location / {
# 构建缓存文件路径(支持目录索引)
set $cache_file "/data/cache/$host$uri/index.html";
# 若 URI 以 / 结尾,尝试 index.html;否则尝试同名 .html
if ($uri ~ ^/(.*)/$) {
set $cache_file "/data/cache/$host/$1/index.html";
}
if ($uri !~ \.) {
set $cache_file "/data/cache/$host$uri.html";
}
<pre class="brush:php;toolbar:false;"># 尝试缓存文件 → 回源到 PHP 处理
try_files $cache_file @php;}
location @php { include fastcgi_params; fastcgi_pass 127.0.0.1:9000; fastcgi_param SCRIPT_FILENAME /var/www$uri.php; }
⚠️ 注意:if 在 location 中慎用(有性能和逻辑陷阱),更健壮的方式是用 map 预计算路径:
map $uri $cache_path {
~^(?<p1>.*)/$ /data/cache/$host$p1/index.html;
~^(?<p2>.*)\.(.*)$ /data/cache/$host$p2.$2;
default /data/cache/$host$uri/index.html;
}
<p>server {
location / {
try_files $cache_path @php;
}
}
</p></p2></p1>
3. 结合 proxy_cache 实现“伪三级”降级(缓存 + 静态文件 + 回源)
虽然 proxy_cache 本身不能被 try_files 直接检测,但可通过 error_page 404 = @fallback 绕过,形成「缓存未命中 → 查静态文件 → 还未命中 → 回源」链路:
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=mycache:10m inactive=60m;
<p>server {
location / {
proxy_cache mycache;
proxy_cache_valid 200 302 10m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;</p><pre class="brush:php;toolbar:false;"> # 缓存未命中时,Nginx 返回 404(需开启 proxy_cache_revalidate 或用 add_header X-Cache-Status $upstream_cache_status 辅助调试)
proxy_cache_bypass $arg_nocache;
proxy_no_cache $arg_nocache;
# 关键:缓存未命中时返回 404,交给 error_page 处理
proxy_intercept_errors on;
error_page 404 = @static_fallback;
proxy_pass http://backend;
}
location @static_fallback {
# 尝试读取预生成静态文件
set $static_file "/data/static$uri";
if ($uri ~ /$) {
set $static_file "/data/static$uri/index.html";
}
try_files $static_file @origin;
}
location @origin {
proxy_pass http://backend;
}}
4. 实用技巧与避坑点
-
路径必须绝对且真实存在:
try_files检查的是文件系统路径,不是 URI。确保 Nginx worker 进程有权限读取缓存目录(chown -R www-data:www-data /data/cache)。 -
避免在 root 下滥用 try_files:例如
try_files $uri $uri/ =404是安全的;但若混用变量路径,务必验证所有分支是否收敛,防止路径遍历(加alias或限制root范围)。 -
配合 cache key 与文件名一致性:后端生成缓存文件时,文件名应严格匹配 Nginx 计算出的
$cache_path,建议统一用md5($scheme$request_method$host$uri$args)命名,再用 map 反向映射路径。 -
调试用 $upstream_cache_status:在响应头中添加
add_header X-Cache $upstream_cache_status;,可清晰看到当前请求走的是HIT、MISS还是BYPASS。
不复杂但容易忽略:try_files 的本质是「文件系统探测」,它不关心内容、不触发代理、不执行脚本——只做存在性判断。想让它真正高效,缓存文件的生成时机、路径规则、权限配置,一个都不能少。











