一年前曾经折腾过 FastCGI_Cache 缓存加速 WordPress,无奈没上线多久,发现 FastCGI_Cache 会把评论者信息和登陆信息缓存,不知道怎么处理掉,只好下线,后来没再折腾。
简介
目前在用 Memcached 数据库缓存,主题做好缓存,数据库查询可以大大减少,一定程度上减少服务器压力,提点速度。提升很大?有什么缺点?其实对于这个访问量不大,服务器在国外的小博客来说,就是聊胜于无吧。
最近想换一个缓存试试,打算用 redis 替换掉 Memcached,看人家说 OpenResty + Redis 方案不错,琢磨着找时间切换过去。在 DG 上开了个测试机器,试了一圈,还是折中方案(Nginx + Redis Cache)更方便折腾。
然而测试时发现,Redis 会与 FastCGI_Cache 一样把评论者信息和登陆信息缓存,既然最终结果差不多,那还不如直接用 Nginx 内置的 FastCGI_Cache?这样可以省去安装 redis,以及相关几个 nginx 扩展。
Nginx 内置 FastCGI_Cache 缓存,但是不支持自动清除缓存。在 WordPress 新建/修改文章,或者访客提交评论,都不会自动清空相关缓存!Nginx 安装 ngx_cache_purg 扩展 + WordPress 缓存清理插件 Nginx Helper 可以解决这个问题。
安装 ngx_cache_purge
检查是否已安装 ngx_cache_purge
nginx -V 2>&1 | grep -o ngx_cache_purge
一般都不会安装,如果显示 ngx_cache_purge 则已安装。
编译安装 nginx_cache_purge
两种方法:一是基于 OneinStack 升级脚本升级 nginx 把扩展编译进去;而是查看原本编译参数,加上 ngx_cache_purge 直接编译。
基于 OneinStack 升级脚本偷懒方法
下载、解压 ngx_cache_purge 安装包:
cd /root/oneinstack/src
wget --no-check-certificate -c -O ngx_cache_purge-2.3.tar.gz https://github.com/FRiCKLE/ngx_cache_purge/archive/2.3.tar.gz
tar xzf ngx_cache_purge-2.3.tar.gz
cd /root/oneinstack
修改 OneinStack nginx 升级脚本:
nginx_modules_options 中增加扩展配置,在 oneinstack/include 目录,找到 upgrade_web.sh,将 ./configure ${nginx_configure_args} 修改为:
./configure ${nginx_configure_args} --add-module=../ngx_cache_purge-2.3
执行脚本升级 Nginx:
~/oneinstack/upgrade.sh
选择升级 nginx,输入需要升级的版本号。
直接加参数编译
cd /root/oneinstack/src
wget http://labs.frickle.com/files/ngx_cache_purge-2.3.tar.gz
wget http://nginx.org/download/nginx-1.17.5.tar.gz
tar xzf ngx_cache_purge-2.3.tar.gz
tar xzf nginx-1.17.5.tar.gz
cd nginx-1.17.5
nginx -V #查看 nginx 编译参数,最后加上--add-module=../ngx_cache_purge-2.3
./configure --prefix=/usr/local/nginx --user=www --group=www \
--with-http_stub_status_module --with-http_v2_module --with-http_ssl_module \
--with-ipv6 --with-http_gzip_static_module --with-http_realip_module \
--with-http_flv_module --with-ld-opt=-ljemalloc \ # 蓝色部分为你网站当前编译参数,请根据实际修改
--add-module=../ngx_cache_purge-2.3
make #编译
mv /usr/local/nginx/sbin/nginx{,_`date +%F`} #备份nginx
cp objs/nginx /usr/local/nginx/sbin
nginx -V 2>&1 | grep -o ngx_cache_purge
# 显示ngx_cache_purge表示已经安装成功
配置 FastCGI_Cache
fastcgi_cache_path 放到 tmpfs 内存中,比放在硬盘上更快。CentOS 目录在 /dev/shm,Ubuntu 和 Debian 在 /run/shm。使用 df -h /var/run 命令查看空间大小。
创建缓存目录
比如,在 run/ 目录下创建 nginx-cache
mkdir -p /var/run/nginx-cache
修改网站配置文件
下面为实例,蓝色字体部分请根据实际修改。
#如果缓存多站点则把下面四行放到nginx.conf 中
fastcgi_cache_path /var/run/nginx-cache levels=1:2 keys_zone=WORDPRESS:192m inactive=1d;
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 80;
listen 443 ssl http2;
ssl_certificate /usr/local/nginx/conf/ssl/cyhour.com.crt;
ssl_certificate_key /usr/local/nginx/conf/ssl/cyhour.com.pem;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
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+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_timeout 10m;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_buffer_size 1400;
add_header Strict-Transport-Security max-age=15768000;
ssl_stapling on;
ssl_stapling_verify on;
server_name cyhour.com www.cyhour.com;
##access_log /data/wwwlogs/cyhour.com_nginx.log combined;
access_log /data/wwwlogs/cyhour.com_nginx.log main;
index index.html index.htm index.php;
root /data/wwwroot/cyhour.com;
if ($ssl_protocol = "") { return 301 https://$host$request_uri; }
if ($host != cyhour.com) { return 301 $scheme://cyhour.com$request_uri; }
include /usr/local/nginx/conf/rewrite/wordpress.conf;
#error_page 404 /404.html;
#error_page 502 /502.html;
set $skip_cache 0;
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/|/go/|/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;
}
location ~ [^/]\.php(/|$) {
#fastcgi_pass remote_php_ip:9000;
fastcgi_pass unix:/dev/shm/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;
}
include custom.conf;
location ~ /purge(/.*) {
allow 127.0.0.1;
allow 1.1.1.1;#此处为服务器公网IP地址
deny all;
fastcgi_cache_purge WORDPRESS "$scheme$request_method$host$1";
}
location ~ .*\.(gif|jpg|jpeg|png|bmp|swf|flv|mp4|ico)$ {
#expires 30d;
#access_log off;
expires max;
}
location ~ .*\.(js|css)?$ {
expires 7d;
access_log off;
}
location ~ /\.ht {
deny all;
}
}
我这里把「# 登录用户和评论过的用户不展示缓存」部分注释掉了,所有用户看到的都是缓存。另外,不需要缓存的重定向规则,需要放到「# 指定页面不展示缓存」之后,否则排除缓存规则无法生效。
比如,老头把 /go/ 外链跳转目录设置为不缓存,include custom.conf; 里面有跳转规则 rewrite ^/go/(.*)$ /ooxx/xxooxxoo.php?oox=$1 last;,那么 一定要把 include custom.conf; 放到「# 指定页面不展示缓存」之后,否则 /go/ 还是会被缓存。(亲测)
使 nginx 配置生效
nginx -t
先检查一下配置,确认无误,重启 nginx
service nginx reload
安装 Nginx Helper 插件
前面说过 FastCGI_Cache 不支持自动清除,WordPress 可以安装 Nginx Helper 插件通过 nginx_cache_purge 接口自动清理缓存。
后台搜索 Nginx Helper 插件,安装,激活,Enable Purge,Caching Method 选 nginx Fastcgi cache (requires external settings for nginx),其余使用默认配置即可。
插件作者定义缓存路径是 /var/run/nginx-cache ,如果自定义缓存路径,可能会导致插件无法找到缓存文件删除!
解决办法是在 WordPress 根目录下 wp-config.php 中新增如下代码即可:
//根据实际情况定义缓存的存放路径 define( 'RT_WP_NGINX_HELPER_CACHE_PATH','/tmp/wpcache');
如果上述定义路径代码不生效,可以试试使用软连接:
ln -s /var/run/nginx-cache /tmp/wpcache
如不想使用插件,可以使用 Nginx Helper 纯代码版。
检查 FastCGI_Cache 是否正常工作
打开网页,F12 打开开发者工具,查看 HTTP 的响应头部,可以看到 x-cache 状态。
HIT 代表命中缓存 MISS 代表没有找到缓存 BYPASS 代表跳过缓存 EXPIRED 代表缓存过期
还可以刷新站点,看缓存目录是否增大。
du -sh /var/run/nginx-cache
温馨提示:开启 FastCGI_Cache 需谨慎!!!上线前需先测试,修改主题解决以下两个问题:1.fastcgi_cache 可能会缓存评论者名称和邮箱信息;2.如果在登陆状态回复评论,会缓存登陆界面。
修改 WordPress 主题匹配 FastCGI_Cache 静态化缓存
静态化缓存,可能会带出一些问题,比如前面说的,FastCGI_Cache 可能会缓存评论者名称和邮箱信息;如果在登陆状态回复评论,会缓存登陆界面;WP-PostViews 不计数……下面记录一下折腾过程,有需要参考一下。
WordPress 让管理员在前台匿名以避免CDN/静态缓存
作者:成航先森,这个可以避免把管理员访问网页被缓存。(其实前面规则按道理就不会缓存登录用户以及已知评论者,不过去年折腾时实测确实是会缓存)
/*
** 让管理员在前台访问匿名
** http://www.capjsj.cn/make_known_users_anonymous.html
*/
function make_known_users_anonymous() {
global $current_user;
if(!is_admin() && $_GET['preview'] != 'true'){
$current_user = array(
'user_login' => '',
'user_email' =>'',
'user_level' => '',
'user_firstname' => '',
'user_lastname' => '',
'display_name' => '',
'ID' => '',
'user_url' => '',
);
}
return $current_user;
}
add_action( 'init', 'make_known_users_anonymous' );
主题评论框表单修改
ajax 提交评论部分可能会有设置 cookies 记住评论者信息代码:
$user = wp_get_current_user();
do_action('set_comment_cookies', $comment, $user);
亲测,把这两行注释掉,对所有用户缓存情况下,还是会把评论者信息缓存,展示给其他用户。
因为评论表单代码可能这样子:
<div id="comment-author-info">
<p class="comment-form-author">
<input type="text" name="author" placeholder="昵称<?php if ($req) echo "(必填)"; ?>" id="author" class="commenttext" value="<?php echo $comment_author; ?>" tabindex="1" />
</p>
<p class="comment-form-email">
<input type="text" name="email" placeholder="邮箱<?php if ($req) echo "(必填)"; ?>" id="email" class="commenttext" value="<?php echo $comment_author_email; ?>" tabindex="2" />
</p>
<p class="comment-form-url">
<input type="text" name="url" placeholder="网址" id="url" class="commenttext" value="<?php echo $comment_author_url; ?>" tabindex="3" />
</p>
</div>
把表单中 value="<?php echo $comment_******; ?>"
直接删除或者改成 value="" 也许就好了。
浏览数不更新
页面静态化后,原本 php 统计浏览数会失效,导致浏览数不更新。解决方法:CDN后用Ajax动态提交、显示文章阅读量,cookies避免重复刷新
注:目前在用 WP-Postviews(文章浏览数)代码精简版
在 footer.php 中添加 ajax 代码
注意需要将前台显示访问量标签 ID 或 class 名称须与主题匹配。
<?php
if( defined( 'FastCGI_Cache' ) && FastCGI_Cache ): // CDN、开缓存wp-config.php开启缓存 ?>
<script type= "text/javascript" >
//http://cn.voidcc.com/question/p-rymvrgdr-rc.html
function intlFormat(num) {
return new Intl.NumberFormat().format(Math.round(num*10)/10);
}
function makeFriendly(num) {
if(num >= 1000000)
return intlFormat(num/1000000)+'M';
if(num >= 1000)
return intlFormat(num/1000)+'k';
return intlFormat(num);
}
function GetCookie(sName) {
var arr = document.cookie.match(new RegExp("(^| )"+sName+"=([^;]*)(;|$)"));
if(arr !=null){return unescape(arr[2])};
return null;
}
var postviews_cook=GetCookie("postviews-<?php the_ID();?>");
if ( postviews_cook == null ){
jQuery.ajax({ type:'POST', url: "<?php echo admin_url('admin-ajax.php');?>" , data:"postviews_id=<?php the_ID();?>&action=postviews",
cache:false,success: function(postviews_count){ jQuery("#main #post-<?php the_ID();?> .views").text('Views:' + makeFriendly( postviews_cook ) );document.cookie="postviews-<?php the_ID();?>=" + postviews_count;} });
} else {
jQuery("#main #post-<?php the_ID();?> .views").text('Views:' + makeFriendly( postviews_cook ) );
};
</script>
<?php endif; ?>
主题 functions.php 添加代码
if( defined( 'FastCGI_Cache' ) && FastCGI_Cache ){ // CDN、开缓存wp-config.php开启缓存
/*
* 缓存时更新浏览量-有缓存
* http://www.capjsj.cn/ajax_cookies_views.html
*/
function postviews_cache(){
if( empty( $_POST['postviews_id'] ) ) return;
$post_ID = $_POST['postviews_id'];
if( $post_ID > 0 ) {
$post_views = (int)get_post_meta($post_ID, 'views', true);
update_post_meta($post_ID, 'views', ( $post_views + 1 ));
echo ( $post_views + 1 );
exit();
}
}
add_action( 'wp_ajax_nopriv_postviews', 'postviews_cache' );
add_action( 'wp_ajax_postviews', 'postviews_cache' );
}
修改 wp-config.php 配置
加入下面代码,然后重启 php 即可:
define('FastCGI_Cache', true);
如使用 WP-Postviews 插件,wp-config.php 中,加入下面这行代码:
define('WP_CACHE', true);
然后在 WP-Postviews 插件选项中启用「使用 AJAX 更新浏览量」即可。
js 记住评论者信息
前面一顿操作,如无意外,WordPress 已经记不住评论用户信息。访客每次评论都需要填写信息,虽然可以「一键填写评论中用户信息」,但是多个自动记住信息可能会更方便。
解决方法:WordPress记住评论用户信息的js版本,直接操作cookie无视缓存、解决JS操作Cookies出现的乱码问题,修复WordPress评论乱码
代码
//设置Cookie
function SetCookie(sName, sValue,iExpireDays) {
if (iExpireDays){
var dExpire = new Date();
dExpire.setTime(dExpire.getTime()+parseInt(iExpireDays*24*60*60*1000));
document.cookie = sName + "=" + escape(sValue) + "; expires=" + dExpire.toGMTString()+ "; path=/;domain=.cyhour.com";
}
else{
document.cookie = sName + "=" + escape(sValue)+ "; path=/;domain=.cyhour.com";
}
}
// 目的: 返回Cookie
function GetCookie(sName) {
var arr = document.cookie.match(new RegExp("(^| )"+sName+"=([^;]*)(;|$)"));
if(arr !=null){return unescape(arr[2])};
return null;
}
//加载用户信息
function LoadRememberInfo() {
var strName=GetCookie("author");
var strEmail=GetCookie("email");
var strHomePage=GetCookie("url");
var bolRemember=GetCookie("chkRemember");
var a_vlaue= document.getElementById("author");
if (a_vlaue != null){
if(bolRemember=="true"){
//通过decodeURIComponent对内容解码
if(strName){document.getElementById("author").value=decodeURIComponent(strName);};
if(strEmail){document.getElementById("email").value=strEmail;};
//通过decodeURIComponent对内容解码
if(strHomePage){document.getElementById("url").value=decodeURIComponent(strHomePage);};
if(bolRemember){document.getElementById("saveme").checked=bolRemember;};
}
if(GetCookie("username")){
document.getElementById("author").value=unescape(GetCookie("username"));
}
}
}
//通过jQuery ready在页面加载时自动从cookies中载入已保存的用户信息
jQuery(document).ready(function($){
LoadRememberInfo();
//给评论提交按钮绑定信息保存函数
$("#respond #submit").click(function(){
SaveRememberInfo();
});
//给评论重置按钮绑定信息移除函数
$("#respond #reset").click(function(){
RemoveRememberInfo();
});
});
//保存信息函数
function SaveRememberInfo() {
var strName=document.getElementById("author").value;
var strEmail=document.getElementById("email").value;
var strHomePage=document.getElementById("url").value;
var bolRemember=document.getElementById("saveme").checked;
//通过encodeURIComponent对内容进行url编码
SetCookie("author",encodeURIComponent(strName),365);
SetCookie("email",strEmail,365);
//通过encodeURIComponent对内容进行url编码
SetCookie("url",encodeURIComponent(strHomePage),365);
SetCookie("chkRemember",bolRemember,365);
}
//移除信息函数
function RemoveRememberInfo() {
SetCookie("author",'',365);
SetCookie("email",'',365);
SetCookie("url",'',365);
SetCookie("chkRemember",'false',365);
}
代码中有两处 domain=.cyhour.com,一定要更改成自己博客域名。
将代码加入到 WordPress 主题 js 文件中即可,比如加入到 comments-ajax.js 最后。如果没有 ajax 评论,就没有 comments-ajax.js,可以将代码保存为 saveinfo.js ,然后引入即可。
修改 comments.php
编辑主题 comments.php 文件,找到提交留言按钮代码,在合适位置添加勾选框:
<input type="checkbox" id="saveme" value="saveme" checked="checked" title="记住我,下次回复时无需重新输入个人信息。" /><label for="comment_mail_notify">记住我</label>
添加后代码,仅供参考,需根据实际修改:
....以上省略....
<p class="form-submit">
<input type="checkbox" id="saveme" value="saveme" checked="checked" title="记住我,下次回复时无需重新输入个人信息。" /><label for="comment_mail_notify">记住我</label>
<input id="submit" name="submit" type="submit" tabindex="5" value="发表留言(Ctrl+Enter)"/>
<?php comment_id_fields(); do_action('comment_form', $post->ID); ?>
</p>
....以下省略....
WordPress 回复评论自动添加@评论者
作者:露兜
这个非必需,我这里启用 444 级评论嵌套,不过只显示 2 级,不加上@评论者,有时候可能不知道谁回复谁。原本是 js 代码添加,原本担心让管理员在前台匿名后,管理员无法在前台回复评论,而原本 js 添加 @ 功能后台回复无效,于是换上这个。
在当前主题 functions.php 中添加以下代码(会直接将 @ 信息写入数据库):
// 评论添加@,by Ludou
function ludou_comment_add_at( $commentdata ) {
if( $commentdata['comment_parent'] > 0) {
$commentdata['comment_content'] = '@<a href="#comment-' . $commentdata['comment_parent'] . '">'.get_comment_author( $commentdata['comment_parent'] ) . '</a> ' . $commentdata['comment_content'];
}
return $commentdata;
}
add_action( 'preprocess_comment' , 'ludou_comment_add_at', 20);
如果你不想将 @评论者 写入数据库,可以使用下面的代码:
// 评论添加@,by Ludou
function ludou_comment_add_at( $comment_text, $comment = '') {
if( $comment->comment_parent > 0) {
$comment_text = '@<a href="#comment-' . $comment->comment_parent . '">'.get_comment_author( $comment->comment_parent ) . '</a> ' . $comment_text;
}
return $comment_text;
}
add_filter( 'comment_text' , 'ludou_comment_add_at', 20, 2);
卸载 Memcached
Memcached 是数据库缓存,一般开启 FastCGI_Cache 静态化缓存,Memcached 基本上就没太大作用,与 FastCGI_Cache 一样,第二次访问才缓存。
结束进程并取消开机启动:
killall memcached && chkconfig memcached off && chkconfig --del memcached
查找所有 Memcached:
find / -name memcached
然后删除掉,比如:
rm -rf /run/memcached /run/lock/subsys/memcached /usr/bin/memcached /usr/local/memcached /usr/local/memcached/include/memcached /usr/local/memcached/bin/memcached /etc/rc.d/init.d/memcached /var/spool/mail/memcached
后记:重新安装上 Memcached
虽然大部分内容已经静态缓存,但还是有部分没有缓存,Memcached 还是有点用处。
OneinStack 安装 Memcached 以及 php-memcached 扩展:
cd /root/oneinstack
./install.sh --memcached
./install.sh --php_extensions memcached
使用方法参考:WordPress 启用 Memcached 动态缓存
参考资料
- 使用 Nginx 中的 fastcgi_cache 为 WordPress 缓存加速
- WordPress 优化 - 利用 Nginx fastcgi_cache 缓存加速
- Nginx开启fastcgi_cache缓存加速,支持html伪静态页面
- WordPress开启Nginx fastcgi_cache缓存加速方法-Nginx配置实例
- WordPress 用上 Nginx fastcgi_cache 缓存教程,给博客再提速
- WordPress 让管理员在前台匿名以避免CDN/静态缓存
- CDN后用Ajax动态提交、显示文章阅读量,cookies避免重复刷新
- WP 使用 FastCGI Cache 实现高效页面缓存
- WordPress记住评论用户信息的js版本,直接操作cookie无视缓存
- 解决JS操作Cookies出现的乱码问题,修复WordPress评论乱码
- WordPress回复评论自动添加@评论者
-- 完 --
我也折腾过,后来还是还原了。感觉不怎么好用。
@奶爸建网站笔记 目前用着感觉还行,就是要折腾的话就没那么方便。