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; } }
问题复现步骤
- 首次访问
/,PHP后端生成缓存文件/cache/_index.html - 再次访问
/,Nginx直接返回缓存文件,完全符合预期 - 删除缓存文件后立即访问: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) - 紧接着第二次访问
/:请求正常转发到PHP后端,生成新的缓存 - 如果删除缓存后等1分钟再访问,也能正常触发PHP生成缓存
调试过程
- 已经设置
open_file_cache off,排除了Nginx自身文件描述符缓存的问题 - 查看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) - 对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)
- 正常情况(删除缓存后过段时间访问):
- 额外测试:如果直接进入Docker容器内部删除缓存文件,Nginx的行为完全正常,不会出现误判
疑问求助
现在我怀疑是不是Docker的文件系统挂载机制导致的缓存问题?或者有没有什么Nginx的隐藏配置我漏掉了?打算尝试在非Docker环境复现,但目前这个现象太诡异了,想问问有没有遇到过类似问题的朋友,或者能给点排查方向的?
备注:内容来源于stack exchange,提问作者BigWhale
相关产品推荐
相关产品推荐

