张戈博客不久前分享过 Nginx 开启缓存为 WordPress 加速的教程,其中分享了 2 种缓存模式:代理模式和本地模式。我一直以为单个 ngx_cache_purge 缓存模块只支持 proxy 代理模式,结果热心的网友回复,其实这个模块也是支持本地缓存的,而且 WordPress 还有配套的插件!
看来还是我孤陋寡闻了!
我像发现了新大陆一般,立马进入折腾状态,幸不辱命,已经成功部署!最爽的是可以通过插件来自动清理文章的对应缓存,解决了前文清理缓存的历史遗留问题。
一、添加模块
本文分享的 Nginx 缓存需要额外编译 ngx_cache_purge 模块。至于下载模块、重新编译以及平滑升级前文已经分享过了,本文就不再赘述了。不会的朋友可以参考前文:
为网站开启 Nginx 缓存加速,支持 html 伪静态页面
Ps:需要重新编译 Nginx,在原有的编译参数上新增一个 ngx_cache_purge 模块,比如:
--add-module=../ngx_cache_purge-2.3
不清楚怎么重新编译和平滑升级的的请参考前文进行操作。
二、Nginx 配置
要用这个缓存功能,建议重新弄一个 server 模块(替换之前的),如下代码是张戈博客目前正在使用的规则(已删除了我自定义的伪静态规则,避免混淆视听):
#################################################################################################### # Nginx 开启 fastcgi_cache-purge 缓存加速,支持 html 伪静态页面 By 张戈博客 # 文章地址:https://zhang.ge/5042.html # 参 考 ①:http://jybb.me/nginx-wordpress-fastcgi_cache-purge # 参 考 ②:https://rtcamp.com/wordpress-nginx/tutorials/single-site/fastcgi-cache-with-purging/ # 转载本文请务必保留以上申明,谢谢合作! #################################################################################################### #下面各个参数的含义请自行百度,我就不赘述了 #下面 2 行的中的 wpcache 路径请自行提前创建,否则可能会路径不存在而无法启动 nginx,max_size 请根据分区大小自行设置 fastcgi_cache_path /tmp/wpcache levels=1:2 keys_zone=WORDPRESS:250m inactive=1d max_size=1G; fastcgi_temp_path /tmp/wpcache/temp; fastcgi_cache_key "$scheme$request_method$host$request_uri"; fastcgi_cache_use_stale error timeout invalid_header http_500; #忽略一切 nocache 申明,避免不缓存伪静态等 fastcgi_ignore_headers Cache-Control Expires Set-Cookie; #Ps:如果是多个站点,以上内容不要重复添加,否则会冲突,可以考虑将以上内容添加到 nginx.conf 里面,避免加了多次。 server { listen 80; #请修改为自己的域名 server_name zhang.ge; index index.html index.htm index.php default.html default.htm default.php; #请修改为自己网站的存放路径 root /home/wwwroot/zhang.ge; set $skip_cache 0; #post 访问不缓存 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/|index.php|sitemap(_index)?.xml") { 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; } #这里请参考你网站之前的配置,特别是 sock 的路径,弄错了就 502 了! location ~ [^/]\.php(/|$) { try_files $uri =404; fastcgi_pass unix:/tmp/php-cgi.sock; fastcgi_index index.php; include fastcgi.conf; #新增的缓存规则 fastcgi_cache_bypass $skip_cache; fastcgi_no_cache $skip_cache; add_header X-Cache "$upstream_cache_status From $host"; fastcgi_cache WORDPRESS; fastcgi_cache_valid 200 301 302 1d; } location / { #此处可以添加自定义的伪静态规则(之前你新增的伪静态规则可以添加到这,没有就不用了) try_files $uri $uri/ /index.php?$args; rewrite /wp-admin$ $scheme://$host$uri/ permanent; } #缓存清理配置(可选模块,请细看下文说明) location ~ /purge(/.*) { allow 127.0.0.1; allow "此处填写你服务器的真实外网 IP"; deny all; fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1"; } location ~* ^.+\.(ogg|ogv|svg|svgz|eot|otf|woff|mp4|ttf|rss|atom|jpg|jpeg|gif|png|ico|zip|tgz|gz|rar|bz2|doc|xls|exe|ppt|tar|mid|midi|wav|bmp|rtf)$ { access_log off; log_not_found off; expires max; } location = /robots.txt { access_log off; log_not_found off; } location ~ /\. { deny all; access_log off; log_not_found off; } #请注意修改日志路径 access_log /home/wwwlogs/zhang.ge.log access; }
请仔细阅读代码中的所有注释,该修改的修改,该创建的创建,该补充的根据实际情况补充,否则使用之后又来找张戈吐槽各种问题了!
三、安装插件
上文已经提到了 fastcgi_cache 有一个量身定做的 WordPress 缓存清理插件:Nginx Helper
所以,接下来我们就去安装这个插件 。非常简单,直接进入 WordPress 后台插件安装界面搜索 Nginx Helper 关键词在线安装即可。
安装后,从后台【工具】==>【Nginx Helper】打开插件设置界面如下所示:
Ps:顺带说一下后面 2 项的含义:
记录插件日志:勾选这个选项后,插件设置下面会显示日志记录存放路径。这个功能主要用来测试插件的设置,比如去已缓存的文字发表一个新的评论,然后看下日志里面是否出现删除记录。
插入缓存信息:勾选这个选项后,前台页面的源代码底部将插入页面的缓存信息,类似如下:
<!--Cached using Nginx-Helper on 2015-05-30 12:34:22. It took 162 queries executed in 1.922 seconds.--> <!--Visit http://wordpress.org/extend/plugins/nginx-helper/faq/ for more details-->
该怎么设置,应该看图就懂了吧?否则张戈苦逼的用中文标注了半天就白费功夫了!
清理模式选择
上图我也标注的比较清楚了,还是详细解释一下吧!
①、purge 模式
这个模式需要保留上文 Nginx 配置中的 purge 清理路径,清理的时候会产生一个请求。
出于安全考虑,一般 purge 都不会完全开放!只有特定的 IP 可以访问,所以,如果用了 CDN 的朋友,再使用模式一,则需要在服务器上的 /etc/hosts 中将网站域名解析为服务器真实 IP,以便插件直接请求 purge 路径,而不用走 CDN 节点,避免请求被拒绝。还是没搞懂的话就放弃这个模式吧!
②、文件模式
模式二是直接清理对应的缓存文件,不需要请求 purge 这个清理路径,所以使用模式二,不需要配置上文 Nginx 的 purge 规则(我个人推荐使用这个模式)。
由于插件作者定义的缓存路径是 /var/run/nginx-cache ,而我们可能会根据服务器实际情况来自定义缓存路径,这样一来,缓存路径的不同就会导致插件无法找到缓存文件并删除!
解决办法:
很简单,在 WordPress 根目录下的 wp-config.php 中新增如下代码即可:
//根据实际情况定义缓存的存放路径 define( 'RT_WP_NGINX_HELPER_CACHE_PATH','/tmp/wpcache');
Ps:不知道添加到第几行的话,可以添加到 define('WPLANG', 'zh_CN'); 的后面即可。添加后建议重载一下 php,确保变量生效(主要针对开启了 PHP 缓存的网站)。
三、效果预览
①、缓存效果
替换新的配置,并且重载 Nginx 之后,访问前台页面,查看 header,会多出一个 X-Cache 标志。
X-Cache 一般会有 3 个状态:MISS、HIT、BYPASS。
- MISS 表示未命中
即这个页面还没被缓存,新发布或刚被删除的页面,首次访问将出现这个状态(图略)。
- HIT 表示缓存命中
打开一个会缓存的页面,比如文章内容 html 页面,F5 刷新几次即可在 F12 开发者模式当中的 Header 头部信息中看到如图缓存命中状态:
- BYPASS 表示缓存黑名单
即页面路径在 Nginx 规则中被设置成不缓存(set $skip_cache 1;),比如 WP 后台,查看 header:
如果你发现想要缓存的页面却是这个状态,就可以去检查排除规则中是不是包含了这个路径!反之,如果你发现后台登录不了,或者各种登陆态丢失问题,则应该到排除规则中加上该页面路径的关键字。
②、清理效果
这个插件和缓存的搭配非常好用,不管我们是发布文章,还是有人发表评论,插件都能根据我们的设置来清理对应的缓存!比如有人发表了一个自动审核通过的评论(或博主审核通过一条评论),插件将会自动删除评论相关的文章缓存,具体看下上图张戈贴出的标注即可。
如何查看插件是否正常工作呢?很简单,勾选开启插件日志,然后去点击更新一篇旧文章,最后打开插件日志即可看到是否删除记录。
用 Linux 的朋友,可以直接使用 tailf 命令查看该日志,然后去更新文章即可看到效果,如下图所示:
至于要证实是否真的删除了缓存,我们可以先打开浏览器的开发者模式,定位到 network 界面,然后访问刚刚更新的文章,即可看到如下状态:
很明显,缓存已被成功删除,首页看都不用看,肯定也是这个状态了。
好了,本文就分享到这,如果对网站缓存感兴趣的朋友,可以继续翻看张戈博客的相关文章:
Ps:当然,东西肯定是越用越好,目前张戈博客也取消了以前的各种缓存,比如 php 代码缓存等。
最后感谢一下在我博客留言告知的【wordpress 优化】站长!总之一句话,如果发现新的 WordPress 折腾目标,你不会折腾的话,可以留言告诉张戈。
为什么按文章的方法配置之后发现,前台页面第一次访问、后台页面访问都巨慢务必,16秒+,效果恐怖啊,主要是Waiting (TTFB)部分等待时间长。前台HIT之后倒是速度很快。配置之前倒是很快。另外,文中的
地方,是引入的nginx默认的fastcgi.conf,还是下面的几行配置就是这个文件的内容?
不可能巨慢。。肯定是你配置错了。
来膜拜dalao的教程,很给力,有个小问题,文章底部的外链,跳转到不可描述网站了~改了吧~
感谢告知。。挺坑
嗨 博主按你的教程使用了这个插件,添加nginx模块,但是检查Head的时候我这里并没有发现有X-CACHE啊??是不是没有生效?怎么可以判断呢?请指点 谢谢
对了 还有expires 这个是怎么实现的?看过YS的网页优化里建议有这一条,百度了一下配置上去了,在检测首页的时候可以看到,但是在文章页面的时候就没有了,是我设置有问题么?谢谢
编辑一下回复.
刚百度了一下 发现这篇文章
http://www.cnxct.com/several-reminder-in-nginx-fastcgi_cache-and-php-session_cache_limiter/
好像明白了点什么,但是又抓不到关键的地方,,博主能否给点帮助?谢谢
redis fastcgi wp-super w3-total 哪个缓存好些
请教下,加入站点配置后检查出现这个怎么弄啊?
配置贴出来
在参 考 ②中网址中看了下
原来要把server前的代码放到nginx.conf才行。再顺便请教一下,纯代码版里用?purge=all清除不了缓存啊,进服务器看缓存文件还在
并不是一定要放到nginx.conf,而是要求放到 http{}里面,也就是放到 server{} 之外即可。
你可以研究下为啥失效。。
张大神!你好!请问我有一个在线支付插件,不能缓存,使用了fastcgi_cache后,支付页面已经换成,不能进行微信和支付宝支持。请问有什么办法可以让这个插件不缓存或者这个页面也不换成!麻烦告知一下
求救、求救。大神!
测试了下,成功了,但有个疑问。
为什么你的这个站连HTML都能304到本地,而按你文章中的方法,可以hit成功,但类似于本文章的HTML页面却只能200,而不能304到本地?
请问你是如何做到的?
为什么我配置好后,浏览器开发者工具这里没显示X-CACHE这个属性
为什么我配置好后,浏览器开发者工具这里没显示X-CACHE这个属性
配置文件如下,重启nginx未报错,没有生成缓存
server{
listen 80;
#listen [::]:80;
server_name http://www.wanvi.net wanvi.net;
index index.html index.htm index.php default.html default.htm default.php;
root /home/wwwroot/www.wanvi.net;
ssl_prefer_server_ciphers on;
if ($server_port = 80 ) { return 301 https://$host$request_uri; }
include rewrite/wordpress.conf;
#error_page 404 /404.html;
# Deny access to PHP files in specific directory
#location ~ /(wp-content|uploads|wp-includes|images)/.*\.php$ { deny all; }
include enable-php.conf;
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}
location ~ .*\.(js|css)?$
{
expires 12h;
}
location ~ /.well-known {
allow all;
}
location ~ /\.
{
deny all;
}
access_log /home/wwwlogs/www.wanvi.net.log;
}
#路径需要提前创建好
fastcgi_cache_path /tmp/wpcache levels=1:2 keys_zone=WORDPRESS:250m inactive=1d max_size=500m;
fastcgi_temp_path /tmp/wpcache/temp;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
fastcgi_cache_use_stale error timeout invalid_header http_500;
fastcgi_ignore_headers Cache-Control Expires Set-Cookie;
server
{
listen 443 ssl http2;
#listen [::]:443 ssl http2;
server_name http://www.wanvi.net wanvi.net;
index index.html index.htm index.php default.html default.htm default.php;
root /home/wwwroot/www.wanvi.net;
ssl_certificate /usr/local/nginx/conf/ssl/wanvi.net.crt;
ssl_certificate_key /usr/local/nginx/conf/ssl/wanvi.net.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers "TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5";
ssl_session_cache builtin:1000 shared:SSL:10m;
# openssl dhparam -out /usr/local/nginx/conf/ssl/dhparam.pem 2048
ssl_dhparam /usr/local/nginx/conf/ssl/dhparam.pem;
include rewrite/wordpress.conf;
#error_page 404 /404.html;
# Deny access to PHP files in specific directory
#location ~ /(wp-content|uploads|wp-includes|images)/.*\.php$ { deny all; }
include enable-php.conf;
# …………………此部省略……………………
set $skip_cache 0;
#post访问不缓存
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/|index.php|sitemap(_index)?.xml") {
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;
}
#这里请参考你网站之前的配置,特别是sock的路径,弄错了就502了!
location ~ [^/]\.php(/|$) {
#fastcgi_pass remote_php_ip:9000;
fastcgi_pass unix:/tmp/php-cgi.sock;
fastcgi_index index.php;
include fastcgi.conf;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
#新增的缓存规则
fastcgi_cache_bypass $skip_cache;
fastcgi_no_cache $skip_cache;
add_header X-Cache "$upstream_cache_status From $host";
add_header Cache-Control max-age=0;
add_header Nginx-Cache "$upstream_cache_status";
add_header Last-Modified $date_gmt;
add_header X-Frame-Options SAMEORIGIN; # 只允许本站用 frame 来嵌套
add_header X-Content-Type-Options nosniff; # 禁止嗅探文件类型
add_header X-XSS-Protection "1; mode=block"; # XSS 保护
etag on;
fastcgi_cache WORDPRESS;
fastcgi_cache_valid 200 301 302 1d;
}
#缓存清理配置(可选)
location ~ /purge(/.*) { #为防止转义,请去掉{ /之间的空格
allow 127.0.0.1;
#此处填写你的服务器IP
allow 120.79.s.s;
deny all;
#请注意此处的WORDPRESS要与上面的keys_zone保持一致
fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
}
# …………………此部分省略……………………
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$
{
expires 30d;
}
location ~ .*\.(js|css)?$
{
expires 12h;
}
location ~ /.well-known {
allow all;
}
location ~ /\.
{
deny all;
}
access_log /home/wwwlogs/www.wanvi.net.log;
我看你网站不是已经有X-CACHE头部了
张哥,不好意思,闹笑话了。我仔细看代码中多次引入了php,按照读取顺序,优先读取了enable-php.conf;

我咋发现一来贵博客,我的驱动就崩溃了!还是频繁重复崩溃!什么情况这是?
这个还是有点不懂.可以详细教下吗?
你好,请问开启了FastCGI缓存还有必要开启php opcache缓存吗?
如果不使用purge模式,那是不是就可以不用装ngx_cache_purge 模块了。
张老师你好!请问:我现在已经配置了Fastcgi-cache,我还需要配置proxy-cache 并使用ngx-cache-purge模块吗?
我的情况是:配置了fastcgi以后,访问网站比如主页的时候,我看到VPS后台里面仍然会开5个php-fpm进程,VPS的CPU依然满载。这跟我的理解/期待不一样。我的想法是它应该不再去请求php-fpm了,而是直接从缓存读取文件然后返回给访问者客户端。而各种网页加载速度评分却又都很高,比如主页100分,99分这样的。但从后台资源的占用量来看,这似乎并不是我想要的。
附:我现在的理解程度仅限于这样:proxy-cache和fastcgi cache的区别。
搜遍网络都没有答案,所以麻烦老师为我做下解答,谢谢!
你的缓存是设置在 location ~ [^/]\.php(/|$)
这php下面的,
这样如果伪静态的话,postname.html的话,是不是就没办法缓存了?
你是缓存在 *.php 下面的。却php页面的才缓存,
如果我是自定义链接的
postname.html这种html链接的就没办法缓存了吗?
WordPress是伪静态,虽然你是访问的XXX.html,实际上nginx会try到php(伪静态),所以只需要在php那里设置就行。
如果是多站点的话要怎么配置哇?
善用搜索:https://zhang.ge/5067.html
已解决,感谢张戈大佬!
fastcgi_temp_path /tmp/wpcache/temp; 这个文件夹里什么都没有生成
fastcgi_cache_path /tmp/wpcache; 这个文件夹生成了很多缓存
这是正常现象吗?
N个页面中有一个页面出了点小问题,需要刷这一个页面url的缓存,要怎么操作呀?
/purge/* 这个入口就是清理指定缓存的,不过简单的办法就是安装文章中的清理插件,然后去更新一下文章,就会自动清理改文章缓存。
这个入口是用在purge模式的吗?我用的是您推荐的文件模式,这个入口进不去的吧,插件装了,我点清除缓存之后,文件还是在的
插件无法清理的话,一般是缓存键值设置不对,要对比下插件的缓存key和nginx设置的key是不是一样的组合
你好,我配置好fastcgi后,效果拔群。但唯独有一个小细节和其他插件(比如wp super cache)有不同,估计是BUG?
我简单描述一下:假设网站的TAG标签的url为:baidu.com/tag/团子头 ,在chrome里复制链接后,会变成编码比如:https://bobopic.com/tag/%e5%9b%a2%e5%ad%90%e5%a4%b4 ,这里的字母都是小写的。
但如果在文章中插入,或者主题调用一些TAG标签后,html代码中的网址就是:baidu.com/tag/%E5%9B%A2%E5%AD%90%E5%A4%B4。字母都是大写的。
这在fastcgi看来就是2个缓存链接了。
后台设置的:发布文章清除tag ,只会清楚小写链接的缓存,而大写链接的缓存依旧是旧内容。。
希望我描述清楚了。
涉及链接:
baidu.com/tag/%E5%9B%A2%E5%AD%90%E5%A4%B4
baidu.com/tag/%e5%9b%a2%e5%ad%90%e5%a4%b4
更换其他缓存插件,这两种大小写链接都被视作同一个缓存目标,会一起被刷新的。 这在fastcgi中,该怎么更改优化呢? 请帮帮忙,谢谢。
看了下应该不能直接解决这个问题,这部分内容属于fastcgi_cache_key 里面的 request_uri 里面的一部分,没有忽略大小写的机制。粗暴解决的话,先将网站存量的数据全部转大写或者转小写,同时从源头固定为大写或小写...
更好的方案暂时没想到。
清理不掉这个好解决,修改清理逻辑,遇到tag的就同时无脑清理小写和大写即可
太快了,还在阅读其他人的评论,就收到了你的回复,谢谢。
【“粗暴解决的话,先将网站存量的数据全部转大写或者转小写,同时从源头固定为大写或小写...”】
和
【修改清理逻辑,遇到tag的就同时无脑清理小写和大写即可】
感觉似乎后面这条更简单,就是无脑清理大小写。
那么问题来了,张哥,怎么清理?能帮一下吗? 我这边让这个卡住了。
搞笑死了,逼得我在【不缓存】的哪里,添加了一个 /tag/* ,但感觉不是长久之计。毕竟文章相关的tag才多少嘛,因小失大。
不知道为啥一直是BYPASS状态
懂了,评论过的用户不展示缓存~~
加了缓存后,查看nginx错误访问日志中有这个情况,可以麻烦张哥看一下什么情况嘛
2023/01/17 02:33:46 [error] 2460823#0: *8369 attempt to set ngx.header.HEADER after sending out response headers while sending to client, client: 访客ip地址, server: 站点域名, request:
你好大佬问个问题 希望可以答复 我比较小白 就是怎么样不缓存点赞和收藏 每次点都会响应半天