5 月份,张戈博客分享了一篇《Nginx 开启 fastcgi_cache 缓存加速,支持 html 伪静态页面》的文章。文中也提到了 WordPress 有一款名为 Nginx Helper 的插件是这个功能的绝佳搭配。
一、问题描述
不过,最近通过朋友反馈及我自己亲测发现了一个严重的问题:
Nginx Helper 设置界面有一个一键清理缓存的按钮【Purge Entire Cache】,只要在后台点击这个按钮,前台就跪了。当然,如果对登录用户不显示缓存,那么登录用户访问是正常的。
二、分析原因
分析了一下原因:【Purge Entire Cache】这个按钮按下后会删除 Nginx 所有的缓存,但是却不会重载(启)Nginx。那么问题来了,当在前台请求需要展示缓存的页面时,Nginx 将继续调用之前的缓存文件,然而所有缓存文件却被这个插件删除了,所以这个页面就 502 了!
清理前可以看到如图缓存文件夹:
但是清理后,就没了,而且也不会在生成。因为这样强行全部删除并没有“通知”Nginx …这时候,网站就打不开了。当然,如果是设置了登录用户或已评论用户不展示缓存,那么网站会实时展示正常打开。但是要展示缓存页面就会 502 了,因为 Nginx 自己都找不到路径了。。。
三、部署解决
不难理解,要解决这个问题,比如给一键清理功能绑定一个重载 Nginx 的机制。但是一般情况下 php 并没有权限去重载或重启 Nginx 。所以,要继续使用这个一键清理功能,就只能授予 php 重启 Nginx 的权限,还需要将重启 Nginx 的命令集成到插件才行。
①、授权 php 执行系统命令
php 重启 nginx 功能,张戈博客之前已经分享过相应的办法了,请先参考部署该功能:
php 平滑重启 nginx,彻底清除 WordPress 的静态缓存
②、将重载命令加入到一键清理函数
部署 OK 之后,编辑 Nginx helper 插件下的 purger.php 文件,找到如下函数:
function true_purge_all(){
$this->unlinkRecursive(RT_WP_NGINX_HELPER_CACHE_PATH, false);
$this->log( “* * * * *” );
$this->log( “* Purged Everything!” );
$this->log( “* * * * *” );
}
如下在函数中添加重载 nginx 的代码即可:
function true_purge_all(){
$this->unlinkRecursive(RT_WP_NGINX_HELPER_CACHE_PATH, false);
exec(EscapeShellCmd(“/opt/reload_nginx.sh”));//一键清理后重载 nginx
$this->log( “* * * * *” );
$this->log( “* Purged Everything!” );
$this->log( “* * * * *” );
}
好了,现在点击一键清理功能,缓存会全部删除,而且 nginx 也会重载,前台网站也就不会跪了。
四、其他完善
当然,经常有人反馈偶尔更新文章,前台并不会刷新。其实,这本文陈述的情况也有关系。在使用【删除模式】时,单篇文章的缓存被清理后,也不会重载 Nginx。此时,如果此文的缓存是存放在内存的话,前台肯定就不会刷新了!
所以,我们有必要给单个清理功能也绑定一个重载 Nginx 的机制。此处为了节省数千个字,张戈决定提供全部修改好的 Nginx Helper 插件,需要的自行下载重新安装这个插件即可:
地址一点击下载
×
版权说明
本站提供的下载内容版权归本站所有。转载 必须 注明出处!* 标有 “转载” 字样的文章,内容版权归原作者所有。
不同意
同意并下载
地址二点击下载
×
版权说明
本站提供的下载内容版权归本站所有。转载 必须 注明出处!* 标有 “转载” 字样的文章,内容版权归原作者所有。
不同意
同意并下载
你可能会疑问为毛删除单个页面后,这个页面却还能打开?和删除全部不是一样的机制吗?
分析了下,如果类比删除全部缓存带来的问题,删除单个页面应该也会出现该页面打不开的情况才对。不过,细想了一下,解释很简单。因为删除全部缓存会破坏缓存的文件目录结构,而删除单个页面只是删除一个缓存文件,缓存的目录结构并未被破坏。
通俗来说:缓存的目录结构如同 Nginx 的一个行车路线,只有不破坏这个路径,才能正常行驶。当然了,你破坏了这个行车路线,重载一下 Nginx 它又能重新规划了。
五、更多花絮
当我发现这个问题,并解决后,还给这插件的作者发了 BUG 反馈邮件。蹩脚的中式英语并不影响交流,哈哈!
感兴趣的可以凑合看看:
Hello Zhang Ge,
Thanks for contacting us. This is Dinesh from rtCamp.
Sorry to hear about the problem you are facing.
Please verify if the Nginx Helper plugin is properly configured from its settings page.
As you are using Nginx FastCGI caching and the site is not loading after purging entire cache so I will suggest to try Redis cache. You can configure Redis cache option in Nginx Helper plugin once its enabled on server.
Redis cache support “Custom Purge URL” option so you can add links which you want to purge instead of purging entire cache. Also, reloading of Nginx is not needed for purging cache.
Please feel free to post your query if you are facing any problem on our community support forum (http://community.rtcamp.com/c/wordpress-nginx).
Regards, Dinesh
Hello , rtcamp:
I found a bug with your plugin that named nginx-helper.
When we click zhe Button [Purge Entire Cache], our websites will dead immediately.
Because [Purge Entire Cache] will clean up all of the fastcgi cache,but without reload the nginx .
So nginx can’t find the cache when we request.
To fixed the bug, you could added a action of reload nginx when [Purge Entire Cache] be clicked.
FYI :
exec(EscapeShellCmd(“/opt/reload_nginx.sh”));
But,it must supported by Operating environment.
My post url: https://zhang.ge/5042.html
——————
张戈博客是关注互联网以及分享 IT 运维工作经验的个人博客,由系统运维、脚本编程以及资源分享等分类组成,涵盖了操作系统教程、运维经验、脚本语言以及网络资源等。
永久地址:https://zhang.ge
Dinesh Jain | Project Manager | rtCamp Solutions Pvt. Ltd.
Web: http://rtCamp.com | Skype: dinesh.jain.rtcamp | Twitter: @dineshjain2911
他要我去他们的论坛发帖,一起交流问题。好吧,我就去看了下,并简单的陈述了一下问题和建议,结果并没有什么卵用,因为没人回复【帖子传送门】。。。
最后,写这篇文章时,我还是单独给这哥们又发了一份邮件:
Dear Dinesh ,
Tks for your reply!
I try to post the problem at bbs as your give,but nobody rebply(http://community.rtcamp.com/t/website-will-dead-when-we-click-the-button-purge-entire-cache/5052),so send a email to you again…
Certainly,switch to “redis cache” is a good idea. But I use Nginx Fascgi Caching for a long time, because of it’s simple. furthermore, redis is not installed on my webserver.
Except for the solution I mentioned in my email. The function of “Purge all cache” should be hiddenwhen then plugin used Nginx-Fascgi-caching and set with “Delete local server cache files ” method. Only in this way, the problem will not be triggered by someone who know nothing about this case.
Of course, This problem should be gone when used “Uses the ngx_cache_purge module”….
Regards, Jager
问题你不解决没关系,但至少应该把这个功能隐藏或加上警告吧?这也是对插件用户负责的表现,否则很多不知情的人一点击一键清理后,前台就歇菜了!多么惊恐,谁还敢用。。。。
好了,如果你也存在这个问题,可以参考本文折腾一下。改了半天插件,发现这个插件并不复杂,后续有空自己写几段 PHP 代码就可以替换掉了。
2016-01-24 最新补充:突然想明白了一件事,其实一键清理可以不出现本文提到的问题!那就是定义 nginx 缓存路径是最多使用两级目录,而不能多于两级。
比如,我之前的文章定义的 Nginx 缓存目录都使用了 /tmp/cache/wpcache,这种就是多于两级目录了,Nginx-Heper 删除的时候会直接删除这个路径,如果不重载 Nginx 就不会重新生成目录结构,将导致网站打不开!
简单分析原因,应该是类似于 mkdir 是否带 -p 参数的结果,如果 mkdir 要创建多级目录,中间目录不存在时必须加入 -p 才能成功创建!类比到 Nginx 的缓存,它就没有用到 -p 这种机制,如果多级目录,中间目录不存在,它就傻眼了!
如果是定义成一级或二级目录,比如使用 /tmp/wpcache 就不会出现这个问题,具体原因就不做分析了!大家如果参考了张戈博客之前写的 Nginx 缓存配置,请将缓存文件的路径都修改为二级即可,比如 /tmp/wpcache 。