Coding, Web, Hydrology and more.

Purge Varnish Cache插件在收到评论后无法更新页面缓存的解决方法

P

前言

博客一直用着Purge Varnish Cache这个插件进行Varnish的缓存管理,插件通过Varnish提供的Admin面板进行管理,其功能也相对强大,可以选择在收到新的(修改)评论、发布(编辑)文章、添加(修改)菜单时对指定页面(首页/文章/整个Varnish缓存)进行更新。但实际上上述特性中的第一点并不能实现。

Bug重现及排查

在退出登录后(VCL中设置当登录时Varnish缓存机制不启用),对任意一篇文章进行评论,重新刷新文章页面,发现Response Header中X-Cache的状态依然是Hit

同时评论列表中也没有刚刚发表的评论,后台中该评论显示已经通过,以登录状态重新刷新页面,评论能够正常显示,那么想必是Varnish的缓存没有更新了。

先从Varnish查起,Shell中用varnishstat监视Varnish缓存状态,同时重复上述步骤,发现MAIN.bans并没有CHANGE,也就是说现在可以确定是Purge Varnish Cache插件的问题了。

巧在这个插件提供了debug模式,在wp-config.php中添加define(‘WP_VARNISH_PURGE_DEBUG’, true);即可开启。

继续重复上述的评论步骤,在wp-content\uploads中打开log文件如下

首页的确是更新了,但是第二条语句里的req.http.host和req.url都是空字符,这里本应该是edlinus.cn和评论文章的链接,故猜测插件在获取文章链接时可能出了些问题,遂在插件代码中搜索生成ban命令的代码

参数只有一个url,看来还得找上一层的函数,经过一番查找之后找到了万恶之源

可以看到,插件通过add_action把purge_varnish_comment_post_trigger动作添加到comment_post这个事件上,然而通过Wordpress Codex可以查到:https://codex.wordpress.org/Plugin_API/Action_Reference/comment_post

comment_post这个事件的属性有两个

$comment_ID
The comment that is created.
$comment_approved
1 (true) if the comment is approved, 0 (false) if not

也就是说实质上purge_varnish_comment_post_trigger接受到的参数$ID是$comment_ID也就是评论ID,可以看到插件通过$post = get_post($ID);获得post的object,然而用评论的ID肯定是没法通过get_post直接获得post的object的,那么接下来要解决这个BUG就十分容易了。

解决方案

实际上解决起来非常简单,在传入的$comment对象中,有comment_post_ID这一项字段,通过这个字段就可以通过get_post获得post的object了。

修改为

即可解决问题。

修改后重新评论文章,发现Response Header中X-Cache状态变为MISS,表明Varnish已经成功清空了这个页面的缓存,BUG Fixed!

Bonjour!

About the author

EDLinus

[stay(d) for d in ('determined','diligent','devoted')]

 
By EDLinus
Coding, Web, Hydrology and more.

Meta