关于php:关于-PHP-Opcache-缓存刷新代码重载

6次阅读

共计 1675 个字符,预计需要花费 5 分钟才能阅读完成。

问题背景

通过启用 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 缓存, 使代价最小化。
正文完
 0