Nginx 启用 FastCGI_Cache 将 WordPress 静态化缓存加速

2 Comments

一年前曾经折腾过 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表示已经安装成功

参考资料:LinuxEye,LNMP 安装可以参考旧文

配置 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),其余使用默认配置即可。

点击查看 Nginx Helper 配置

插件作者定义缓存路径是 /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 动态缓存

参考资料

-- 完 --

除非注明,沙唐桔文章均为原创,本文地址 https://cyhour.com/1189/,转载时必须以链接形式注明原始出处。
声明:我们不销售主机,选主机需合法使用。任何主机需定期备份,防止数据丢失。信息以实际为准,评测仅供参考不代表权威!
🔞:Netflix 奈飞 YouTube 合租免费节点Telegram 频道

优化 WordPress 评论回复通知邮件

用上 G Suite 后,域名邮箱自然也托管到 Google,Gmail 配合 Gmail SMTP 插件使用,还行。更改后回复评论提交速度巨慢,肯定与这个评论回复通知邮件有关。 原本使用 VPS Postfix 直接发送,虽然基本上会进垃圾邮件,但是回复评论提交速度很快。再次尝试使用 wp_schedule_single_event 延迟发送评论…

使用 rclone 将 Google Drive 文件同步至 OneDrive

前几天上了博友「灵尘居」的 Office 365 车,1T OneDrive 到手,手机照片一直喂 Google AI,挺方便的,以前还会同步一份到家里的垃圾西数 NAS,不过并不太自动,后来就懒得弄了。 Google 虽然是大厂,但是数据只有一份,还是怕怕,多一个备份不是坏事。苹果 iCloud 不错,但是贼贵,况且我只有一个…
浏览: 137 标签:  ,  ,  ,  ,  ,  , 

尼康 D7100 中文使用说明书 高清 PDF 电子版免费下载

尼康 D7100 说明书是一份介绍详细尼康 D7100 单反官方教程,推荐购买了 D7100 单反博友下载保存参考,以便随时查看一些常用按键操作和使用技巧。 尼康 D7100 简介 尼康 D7100 搭载先进的对象捕捉性能和成像性能,能够忠实还原拍摄细节。高密度的 51 点自动对焦系统准确捕捉目标对象并进行跟踪,…

全网热门公共 BitTorrent Tracker 列表合集 加速BT下载

BT 下载速度取决于其他下载同一资源的用户上传速度。做种「指上传文件数据给其他 BT 用户的行为」用户越多,你的下载速度越快!如果资源没人提供上传,就会完全没有下载速度,而做种用户靠 Peer、DHT、Tracker 获得。 Tracker 是什么? BT 下载的文件都是其他用户上传给你的。 BT 下载速度…
浏览: 67 标签:  ,  ,  ,  ,  ,  , 

Comments:2

  1. 我也折腾过,后来还是还原了。感觉不怎么好用。

    2019.10.30 16:01 # 回复
    1楼

发表留言

Vultr 送$100,搬瓦工年付最低$49,优惠码 BWH3HYATVBJW,更多推荐VPS信息