解决PHP Opcache 缓存刷新、代码重载出现无法更新代码的问题


Posted in PHP onAugust 24, 2020

问题背景

通过启用Opcache的缓存优化,将PHP代码预编译为Opcode缓存到共享内存中供进程反复调用,从而减少了重复从磁盘解析PHP代码的时间消耗,显著的提高了PHP性能,提升了业务性能的调用,但是也引发了一些问题,就是我们每次更新了相应的PHP代码后,web server 无法即时加载到更新后的代码。

解决方案

(一)、设置Opcache脚本验证时间

可以通过更改 Opcache 以下两个配置选项来调整代码重载时间

opcache.revalidate_freq=0 检查脚本时间戳是否有更新的周期,以秒为单位。(如果设置为 0 会导致针对每个请求, OPcache 都会检查脚本更新)

opcache.validate_timestamps=0 如果启用,那么 OPcache 会每隔 opcache.revalidate_freq 设定的秒数 检查脚本是否更新。

PS:在实际生产环境中,为了尽可能达到最优性能,尽量不开启文件更新验证,因为每次验证都会重新预编译PHP代码到共享内存中。

(二)、重启 | 重载 php-fpm 进程

每次重启或重启 php-fpm 进程便会重新解析PHP脚本文件,但是重启 fpm 进程可能会导致请求中断,从而导致写入脏数据 或者 造成事务回滚等一系列异常。

重载相对于重启则平顺很多,不会导致用户请求直接中断,相对来说风险低很多,但是php-fpm 收到reload信号,便会向所有子进程发送SIGGUIT信号,同时注册一个定时器,在规定的时间之内子进程没有退出,接着在发送SIGTERM信号,结束子进程。如果在一秒之内子进程还是没结束 直接发送SIGKILL 强制杀死。

重启php-fpm

service php-fpm restart

重载php-fpm

services php-fpm reload

或 kill -USR2 `cat /usr/local/php/var/run/php-fpm.pid`

(三)、手动清理缓存

除了上面的两种方式,还有更为稳妥一点的缓存清理,我们可以通过opcache_reset()和opcache_invalidate() 函数来刷新Opcache缓存。

opcache_reset() - 重置整个Opcode缓存,所有的PHP脚本将会被重新解析再预编译为Opcode。

opcache_invalidate() - 清除指定脚本缓存,可以传递两个参数,一个是刷新文件路径,一个是force字段, 如果 force 没有设置或者传入的是 FALSE,那么只有当脚本的修改时间 比对应Opcode的时间更新时,脚本的缓存才会失效。

需要注意的是,当PHP以PHP-FPM的方式运行的时候,opcache的缓存是无法通过php命令进行清除的,只能通过http或cgi到php-fpm进程的方式来清除缓存,我们可以编写一个对外接口,来达到清理缓存的目的。

相关实现如下(框架:laravel):

Route::any('cache-reset', function () {
  //重置整个Opcode缓存
  dd(opcache_reset());
});

Route::any('cache-update', function () {
  //清除掉最近一次更新文件的缓存
  exec('git diff --name-only HEAD~ HEAD', $output);
  foreach ($output as $file) {
    $path = base_path($file);
    opcache_invalidate($path, true);
  }
  dd('刷新完成');
});

总结

通过上面的三种策略,可以实现 Opcache 缓存更新的目的,但是在流量高峰期或者大流量的服务端,每次更新缓存都是一件非常损耗资源的事情,Opcache在重建缓存时,也不会禁止其他进程读取,因此就会造成反复新建缓存,因此想要达到最佳的性能调配:

  • 最好不要在高峰期清理缓存
  • 高峰期不要频繁的更新代码,清理缓存,会造成重复新建缓存
  • 如果需要更新,可以尝试削弱服务端权重,实现逐个更新的目的。
  • 如果需要强制更新,尽量选择手动清除缓存的方式,来重建Opcache缓存,使代价最小化。

以上就是解决PHP Opcache 缓存刷新、代码重载出现无法更新代码的问题的详细内容,更多关于PHP Opcache 缓存刷新、代码重载的资料请关注三水点靠木其它相关文章!

PHP 相关文章推荐
深入了解php4(2)--重访过去
Oct 09 PHP
分页详解 从此分页无忧(PHP+mysql)
Nov 23 PHP
从手册去理解分析PHP session机制
Jul 17 PHP
php eval函数用法 PHP中eval()函数小技巧
Oct 31 PHP
2014过年倒计时示例
Jan 31 PHP
php计算数组相同值出现次数的代码(array_count_values)
Jan 20 PHP
PHP动态生成指定大小随机图片的方法
Mar 25 PHP
PHP中利用sleep函数实现定时执行功能实现代码
Aug 25 PHP
Yii2 如何在modules中添加验证码的方法
Jun 19 PHP
PHP设计模式之注册树模式分析
Jan 26 PHP
PHP7导出Excel报ERR_EMPTY_RESPONSE解决方法
Apr 16 PHP
redis+php实现微博(一)注册与登录功能详解
Sep 23 PHP
WordPress免插件实现面包屑导航的示例代码
Aug 20 #PHP
VSCode+PHPstudy配置PHP开发环境的步骤详解
Aug 20 #PHP
Laravel相关的一些故障解决
Aug 19 #PHP
聊聊 PHP 8 新特性 Attributes
Aug 19 #PHP
php提高脚本性能的4个技巧
Aug 18 #PHP
php判断IP地址是否在多个IP段内
Aug 18 #PHP
PHP 8新特性简介
Aug 18 #PHP
You might like
php数组函数序列之array_slice() - 在数组中根据条件取出一段值,并返回
2011/11/07 PHP
php 搜索框提示(自动完成)实例代码
2012/02/05 PHP
PHP代码保护--Zend Guard的使用详解
2013/06/03 PHP
Laravel5.5+ 使用API Resources快速输出自定义JSON方法详解
2020/04/06 PHP
再谈javascript 动态添加样式规则 W3C校检
2009/12/25 Javascript
JS定时器实例
2013/04/17 Javascript
浅析JQuery获取和设置Select选项的常用方法总结
2013/07/04 Javascript
JavaScript实现倒计时代码段Item1(非常实用)
2015/11/03 Javascript
微信开发 js实现tabs选项卡效果
2016/10/28 Javascript
正则表达式替换html元素属性的方法
2016/11/26 Javascript
EasyUI中的dataGrid的行内编辑
2017/06/22 Javascript
jQuery+C#实现参数RSA加密传输功能【附jsencrypt.js下载】
2017/06/26 jQuery
vue2实现数据请求显示loading图
2017/11/28 Javascript
详解如何在React组件“外”使用父组件的Props
2018/01/12 Javascript
React路由管理之React Router总结
2018/05/10 Javascript
脚手架vue-cli工程webpack的作用和特点
2018/09/29 Javascript
Postman的下载及安装教程详解
2018/10/16 Javascript
puppeteer实现html截图的示例代码
2019/01/10 Javascript
微信小程序跳转到其他网页(外部链接)的实现方法
2019/09/20 Javascript
uniapp实现横向滚动选择日期
2020/10/21 Javascript
[36:13]Mineski vs iG 2018国际邀请赛小组赛BO2 第一场 8.16
2018/08/17 DOTA
Linux中安装Python的交互式解释器IPython的教程
2016/06/13 Python
python 使用get_argument获取url query参数
2017/04/28 Python
python中的内置函数max()和min()及mas()函数的高级用法
2018/03/29 Python
解决Pycharm下面出现No R interpreter defined的问题
2018/10/29 Python
python mock测试的示例
2020/10/19 Python
python抢购软件/插件/脚本附完整源码
2021/03/04 Python
奥地利领先的在线药房:SHOP APOTHEKE
2019/10/07 全球购物
酒店副总经理岗位职责范本
2014/02/04 职场文书
2014年骨干教师工作总结
2014/12/19 职场文书
车间主任岗位职责
2015/02/03 职场文书
三好学生个人总结
2015/02/15 职场文书
社区党支部承诺书
2015/04/29 职场文书
获奖感言一句话
2015/07/31 职场文书
Pytorch 中net.train 和 net.eval的使用说明
2021/05/22 Python
Python之matplotlib绘制饼图
2022/04/13 Python