什么是opcache?
Opcache是一种通过将解析的PHP脚本预编译的 字节码(Operate Code)存放在 *共享内存 *中来避免每次加载和解析PHP脚本的开销,解析器可以直接从共享内存读取已经缓存的字节码(Operate Code),从而大大提高PHP的执行效率。
存储预编译字节码的好处就是 省去了每次加载和解析 PHP 脚本的开销。
Opcache的安装和使用
PHP 5.5.0 及后续版本中已经绑定了 OPcache 扩展。 对于 PHP 5.2,5.3 和 5.4 版本可以使用 » PECL 扩展中的 OPcache 库。
安装
OPcache 只能编译为共享扩展。 如果你使用 --disable-all 参数 禁用了默认扩展的构建, 那么必须使用 --enable-opcache 选项来开启 OPcache。
# 当你的PHP版本低于7.0时,你可以去http://pecl.php.net/package/ZendOpcache 根据自己的PHP版
# 本下载相应的opcache版本。比如PHP5.5:http://pecl.php.net/get/zendopcache-7.0.5.tgz
tar -zxvf zendopcache-7.0.5.tgz
cd zendopcache-7.0.5
phpize
./configure --with-php-config=/usr/local/php/bin/php-config
make
make install
# 这时会在php的扩展文件夹内生成opcache.so
# PHP7.0之后自带opcache.so无需安装
编译之后,就可以使用 zend_extension 指令来将 OPcache 扩展加载到 PHP 中。在非 Windows 平台使用 zend_extension=/full/path/to/opcache.so
, Windows 平台使用 zend_extension=C:\path\to\php_opcache.dll
。
配置参数
php.ini
关于opcache的详细参数配置比较核心的参数如下:
opcache扩展位置
zend_extension=opcache.so
启用opcache
opcache.enable=1
使用共享内存大小
opcache.memory_consumption=128
字符串缓存大小
opcache.interned_strings_buffer=8
最大缓存文件数量
opcache.max_accelerated_files=4000
出现异常,立即释放全部内存
opcache.fast_shutdown=1
文件检测周期
revalidate_freq=60
# 以下根据实际情况开启
开启cli模式
opcache.enable_cli=1
最大允许占用内存百分比,超过此限制会重启进程
opcache.max_wasted_percentage=20
如果置为1,则将当前路径加入到文件key中,以避免可能产生的同文件名的文件key冲突
opcache.use_cwd=1
启用文件缓存时间戳
opcache.validate_timestamps=1
缓存清理
方法一:设置Opcache脚本验证时间
revalidate_freq,默认2
检查脚本时间戳是否有更新的周期,以秒为单位。 设置为 0 会导致针对每个请求, OPcache 都会检查脚本更新
validate_timestamps,默认1
如果启用,那么 OPcache 会每隔 opcache.revalidate_freq 设定的秒数 检查脚本是否更新。
方法二:手动清理缓存
使用 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进程的方式来清除缓存
方法三:重启 | 重载 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 -USR2cat /usr/local/php/var/run/php-fpm.pid