谈谈opcache的一些必须注意事项(一不小心服务器内存就爆了)

PHP编程技术 网络投稿 2022-01-20 16:50 1396 0

在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


使用命令获取内存使用情况


1.png





一直监控了很久,使用很正常,调试方向,没错了,


而最后接口返回时间对比一下


优化前

2.png




优化后

3.png



而通过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 配置参数的应用;而最后的实践对比验证也很重要了。



-----------------------------------