谈谈opcache的一些必须注意事项(一不小心服务器内存就爆了)
在PHP的应用中,说到优化,不得不提到opcache,在PHP5.6+,我们可以开启opcache来,提升我们网站的访问速度,所以用好opcache能帮我们提升效率。
在opcache生效中,有两个主要配置
opcache.validate_timestamps=1;
opcache.revalidate_freq=10;
1.当validate_timestamps设置0时, opcache.revalidate_freq的值将失效,validate_timestamps作用主要验证是否要重新生成缓存脚本,PHP将不会检测代码是否改变,这样会导致部署更新的代码后,不会自动生成新的缓存,就导致还是显示原来的旧代码; 当然,可以设置为 0(这样性能最佳的),但是这个一般适合于不频繁更新的PHP 代码,每次更改后需要手动清除 opcache,即需要平滑加载php-fpm。
2.当validate_timestamps设置1时,opcache.revalidate_freq的值将生效,在opcache.revalidate_freq设置的时间值,PHP将会重新生成代码缓存。
接下来看开启opcache 会导致什么问题
首先,我在给两个在运行的PHP项目添加opcache
配置
[opcache]
zend_extension=opcache.so
opcache.enable=1
opcache.memory_consumption=384
opcache.interned_strings_buffer=8
opcache.max_accelerated_files=100000
opcache.max_wasted_percentage=5
opcache.use_cwd=1
opcache.validate_timestamps=1
opcache.revalidate_freq=60
opcache.save_comments=0
opcache.fast_shutdown=1
opcache.consistency_checks=0
项目一:是一个很少的代码更新的PHP项目(主机一)
项目二:是一个频繁更新的PHP项目,cli与php-fpm(主机二)
未开启前,查看两个主机的内存使用情况
主机一:
# free -m
total used free shared buff/cache available
Mem: 7774 1636 636 35 5500 5804
Swap: 0 0 0
主机二:
# free -m
total used free shared buff/cache available
Mem: 15830 6228 2765 1318 6836 7073
Swap: 5887 0 5887
两台配置opcache ,主机二频繁的跟新PHP代码 ,等了一段时间后再查看一下,
主机一:
# free -m
total used free shared buff/cache available
Mem: 7774 1641 630 37 5502 5797
Swap: 0 0 0
主机二:
# free -m
total used free shared buff/cache available
Mem: 15830 14202 339 11208 1288 298
Swap: 5887 0 5887
好家伙,主机二所在的内存使用,差点就满了,主机二所在的地方有比较多的PHP项目,看到这种情况,立马停止了opcache。
问题分析:为什么会出现这种问题呢?
分析一:
可能由于我的PHP项目跟新代码的方式是通过软连所生成的web目录,opcache 是通过文件的真实路径进行缓存的,这就导致了每次部署都会生成缓存字节码,那么就导致了旧的缓存没有被清理,也导致我们的内存无法释放,从而导致内存给撑满了。
分析二:
可能是在 执行cli 命令行下执行此函数并不能清理 php-fpm 下生成的缓存字节码,也会大量产生缓存,会严重消耗内存、cpu。
问题处理:
按照分析是什么原因引起,那就好处理了。
方法一:
平滑重启PHP,但是对于那些频繁跟新的PHP项目并不是很实用,这里略过
方法二:
通过第三方库 cachetool工具,实现对缓存的刷新控制。
Cachetool工具使用
安装cachetool-4.1.1.phar ,版本 PHP >=7.1
下载安装:
curl -sO https://gordalina.github.io/cachetool/downloads/cachetool-4.1.1.phar
chmod +x cachetool-4.1.1.phar
mv cachetool-4.1.1.phar cachetool.phar
最新的可以下载:
curl -sO https://github.com/gordalina/cachetool/releases/latest/download/cachetool.phar
chmod +x cachetool.phar
查看用法:
php /usr/local/cachetool/cachetool.phar --fcgi=/dev/shm/php-cgi.sock
注意:--fcgi参数配置主要为sock和127.0.0.1:9000两种
查看PHP的opcache的缓存状态:
php /usr/local/cachetool/cachetool.phar opcache:status --fcgi=/dev/shm/php-cgi.sock
清除PHP缓存:
php /usr/local/cachetool/cachetool.phar opcache:reset --fcgi=/dev/shm/php-cgi.sock
查看缓存是否已经被清理
以后用法,可以通过更新代码后更新缓存
问题再次出现
本来,以为通过以上的方法,清理每一次上线的代码缓存,就不会导致内存挤满的,可是现实很打脸,内存大概10来分钟,又被挤满了,内存,cpu 直达100%,任何操作都做不了,被迫强制关机。
好了。我们常用的php一般有两种运行方式,一种是php-fpm ,另一种是cli,而我,恰恰忽略cli的运行方式。而Cli运行方式,也会加载读取php.ini配置文件,也会消耗内存。
处理办法:
找了很多的opcache配置解析,发现忽略一个很重要的一个参数opcache.enable_cli,好像发现了,就是这个导致的,这个就是导致cli,占用大量的内存,而且无法清理,而引起系统内存崩溃。
添加配置
opcache.enable_cli=0
使用命令获取内存使用情况
一直监控了很久,使用很正常,调试方向,没错了,
而最后接口返回时间对比一下
优化前
优化后
而通过curl获取点时间
curl -o /dev/null -s -w '%{time_connect}:%{time_starttransfer}:%{time_total}\n' 'http://api.test.com'
0.067740:0.097896:0.098095
总结:
在应用opccache中 。一定要把握opcache.enable_cli 配置参数的应用;而最后的实践对比验证也很重要了。
-----------------------------------