问题背景
通过启用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缓存,使代价最小化。
发表回复