Nginx fcgi_cache对某WordPress站点部分URL不生效问题排查
问题描述
运行多个WordPress站点,Nginx的fcgi_cache在其余站点均正常工作,但其中一个站点的部分URL始终无法缓存,缓存状态头X-Cache始终显示MISS。已确认$skip_cache值为0,排除缓存绕过的可能性。当前Nginx缓存配置如下:
if ($request_method = POST) { set $skip_cache 1; } if ($query_string != "") { set $skip_cache 1; } if ($request_uri ~* "/wp-admin/|/xmlrpc.php|wp-.*.php|^/feed/*|/tag/.*/feed/*|/.*sitemap.*\.(xml|xsl)") { set $skip_cache 1; } if ($http_cookie ~* "comment_author|wordpress_[a-f0-9]+|wp-postpass|wordpress_no_cache|wordpress_logged_in") { set $skip_cache 1; } fastcgi_cache_key "$host$request_uri"; fastcgi_cache wpcache; fastcgi_cache_valid 200 301 302 2h; fastcgi_cache_use_stale error timeout updating invalid_header http_500 http_503; fastcgi_cache_min_uses 1; fastcgi_cache_bypass $skip_cache; fastcgi_ignore_headers Cache-Control Expires; add_header X-Cache $upstream_cache_status;
配置问题分析与修复方案
1. 缺失fastcgi_no_cache配置
当前配置仅设置了fastcgi_cache_bypass $skip_cache;,该指令控制是否绕过缓存直接请求上游,但未设置fastcgi_no_cache $skip_cache;——这个指令控制是否将上游响应写入缓存。即使$skip_cache为0,缺少该配置可能导致Nginx在某些场景下不将响应存入缓存,直接导致后续请求MISS。
修复:添加fastcgi_no_cache $skip_cache;,与fastcgi_cache_bypass配对使用,确保缓存逻辑一致:
fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache; # 新增这一行
2. 上游响应携带Set-Cookie头
Nginx默认不会缓存带有Set-Cookie头的响应,哪怕已经设置fastcgi_ignore_headers Cache-Control Expires也无效。如果该站点的目标URL被WordPress插件/主题强制添加了不必要的Set-Cookie头(比如某些统计插件、未正确配置的优化插件),就会导致缓存无法写入。
排查与修复:
- 用
curl -I命令查看目标URL的响应头,确认是否存在Set-Cookie字段:curl -I https://your-site.com/target-url/ - 如果存在非必要的
Set-Cookie,排查站点内的插件/主题,禁用或调整相关设置;如果确实需要保留Cookie但仍要缓存,可以添加fastcgi_ignore_headers Set-Cookie;(注意:此操作会忽略所有上游Set-Cookie头,可能影响依赖Cookie的功能,需谨慎测试)。
3. 缓存键潜在冲突或不完整
当前fastcgi_cache_key使用$host$request_uri,多数场景下可以唯一标识请求,但如果目标URL存在大小写差异(比如/Page和/page),$request_uri会保留原始大小写,导致生成不同的缓存键。若站点存在此类URL,可能出现缓存命中率低的情况。
修复:可以将$request_uri转为小写后生成缓存键,确保大小写不敏感:
fastcgi_cache_key "$host$uri$is_args$args"; # 改用$uri(自动小写)替代$request_uri
(注:$uri是Nginx规范化后的URI,会自动转为小写并去除多余斜杠,$is_args$args替代$query_string的处理,更严谨)
4. 缓存目录权限问题
虽然其他站点缓存正常,但仍需确认Nginx进程对wpcache缓存池对应的目录有读写权限。可通过以下命令检查:
# 查看缓存池目录位置(在nginx.conf或相关配置中查找proxy_cache_path) grep -r "proxy_cache_path.*wpcache" /etc/nginx/ # 检查目录权限 ls -ld /path/to/wpcache/ # 确保所属用户是nginx运行用户(通常是www-data或nginx) chown -R nginx:nginx /path/to/wpcache/
验证修复
修改配置后,重启Nginx:
systemctl restart nginx
然后多次访问目标URL,查看X-Cache头是否变为HIT,确认缓存生效。
内容的提问来源于stack exchange,提问作者Alijvhr

