try_files的核心作用是避免不必要的磁盘访问,它按顺序检查指定路径,首个存在即处理,否则移交后端或返回错误,从而跳过默认冗余探测。

try_files 的核心作用不是“减少磁盘探测”,而是**避免不必要的磁盘访问**——它通过按顺序检查文件/路径是否存在,并在匹配时直接返回,未匹配时才交给后端(如 PHP-FPM)或返回错误,从而跳过大量默认的、可能失败的文件查找流程。
理解 Nginx 默认行为带来的冗余探测
不配置 try_files 时,Nginx 常依赖 index 指令或隐式查找逻辑。例如:
- 用户请求
/api/user,但没带尾部斜杠,Nginx 可能先尝试找/api/user/index.html、/api/user.html等(取决于 index 和 location 配置); - 静态资源目录中若缺失
favicon.ico,每次请求都会触发一次磁盘查找,反复失败; - PHP 应用常把所有非静态请求都甩给
index.php,但若没显式拦截,Nginx 可能先查/xxx.jpg、再查/xxx.jpg/index.html、再查/xxx.jpg.html……直到 404。
这些试探性查找虽单次开销小,但在高并发下会显著增加 inode 查找、stat() 系统调用和上下文切换,拖慢响应并抬高 I/O 负载。
用 try_files 显式定义“只查这几种,其余全交出去”
关键原则:**列出你真正期望存在的文件路径,其余一律快速移交或拒绝**。常见高效写法:
-
静态资源服务(如前端 SPA):
try_files $uri $uri/ /index.html;
→ 先找真实文件,再找同名目录(含 index),最后兜底到 SPA 入口。不会尝试$uri.html或其他后缀。 -
PHP-FPM 后端(Laravel/WordPress 等):
try_files $uri $uri/ /index.php?$query_string;
→ 明确排除对.php文件的二次查找(比如不查/admin.php/login这类误配),所有动态请求归一交由index.php处理。 -
严格静态托管(禁止目录遍历 & 动态回退):
try_files $uri =404;
→ 存在即返回,不存在立刻 404,完全不触发任何 fallback 查找。
配合其他指令进一步封堵无效路径
try_files 是主干,还需辅以精准的 location 分流:
- 用
location ^~ /static/单独处理静态资源,内部用try_files $uri =404,避免被通用 PHP 规则干扰; - 显式拒绝访问敏感路径:
location ~* \.(htaccess|env|log|ini)$ { return 404; },省去磁盘上找这些文件的过程; - 对已知不存在的固定路径(如
/favicon.ico),可单独配置:location = /favicon.ico { log_not_found off; expires 1d; try_files /static/favicon.ico =404; },关闭日志+缓存+精准定位,杜绝重复 stat。
验证是否生效:看 access.log 和 strace
开启 Nginx 日志中的 $request_filename 变量,观察实际匹配到的物理路径;更直接的方式是临时用 strace -p $(pidof nginx) -e trace=stat,openat -f 抓系统调用,对比启用 try_files 前后 stat() 调用次数与路径——你会看到大量类似 stat("/var/www/html/test.php.html", ...) 的无效调用消失。


















