You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Nginx try_files误判已删除文件存在,导致后续打开报错的问题求助

Nginx try_files误判已删除文件存在,导致后续打开报错的问题求助

大家好,我最近碰到一个特别诡异的Nginx问题,折腾了好久没搞明白,想请教下各位大佬!

问题核心

我用Nginx配合PHP-FPM做静态缓存:先尝试用try_files读取预先生成的静态HTML缓存文件,不存在就转发给PHP生成。但缓存文件被删除后立即访问时,try_files会误判文件还存在,导致后续Nginx尝试打开文件时报错返回404;但第二次访问或者等1分钟再访问,请求又能正常转发到PHP后端了。

环境与配置

我是用Docker容器化部署的,Nginx和PHP-FPM分两个容器:

Docker Compose相关配置

nginx:
  image: nginx:latest
  ports:
    - "${WEB_PORT:-8100}:80"
  volumes:
    - ./.docker/nginx:/etc/nginx/conf.d
    - ./:/var/www/html
  restart: always

Nginx核心配置

server {
    ... ...
    set $bypass_url "/cache/${request_uri}/_index.html";

    location / {
        # 已经关闭了Nginx的文件缓存,排除这个因素
        open_file_cache off;
        try_files $bypass_url $uri /index.php?$args;
    }

    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass php:9000;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_param PATH_INFO $fastcgi_path_info;
    }
}

问题复现步骤

  1. 首次访问/,PHP后端生成缓存文件/cache/_index.html
  2. 再次访问/,Nginx直接返回缓存文件,完全符合预期
  3. 删除缓存文件后立即访问:Nginx返回404错误,日志报错:
    2023/09/28 14:34:32 [error] 22#22: *4 open() "/var/www/html/cache/_index.html" failed (2: No such file or directory)
    
  4. 紧接着第二次访问/:请求正常转发到PHP后端,生成新的缓存
  5. 如果删除缓存后等1分钟再访问,也能正常触发PHP生成缓存

调试过程

  1. 已经设置open_file_cache off,排除了Nginx自身文件描述符缓存的问题
  2. 查看Nginx debug日志,发现try_files阶段居然判定文件存在,但后续打开时又报错:
    2023/09/28 14:02:17 [debug] 21#21: *11 trying to use file: "/cache/_index.html" "/var/www/html/cache/_index.html"
    ...
    2023/09/28 14:02:17 [error] 21#21: *11 open() "/var/www/html/cache/_index.html" failed (2: No such file or directory)
    
  3. 对Nginx进程做strace分析,发现了关键差异:
    • 正常情况(删除缓存后过段时间访问):newfstatat()返回ENOENT(文件不存在),Nginx正常fallback到PHP
    • 异常情况(删除后立即访问):newfstatat()返回文件存在的状态,但后续openat()却报错文件不存在:
      newfstatat(AT_FDCWD, "/var/www/html/cache/_index.html", {st_mode=S_IFREG|0644, st_size=6, ...}, 0) = 0
      openat(AT_FDCWD, "/var/www/html/cache/_index.html", O_RDONLY|O_NONBLOCK|O_LARGEFILE) = -1 ENOENT (No such file or directory)
      
  4. 额外测试:如果直接进入Docker容器内部删除缓存文件,Nginx的行为完全正常,不会出现误判

疑问求助

现在我怀疑是不是Docker的文件系统挂载机制导致的缓存问题?或者有没有什么Nginx的隐藏配置我漏掉了?打算尝试在非Docker环境复现,但目前这个现象太诡异了,想问问有没有遇到过类似问题的朋友,或者能给点排查方向的?

备注:内容来源于stack exchange,提问作者BigWhale

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.21 12:43:15