前言
起源:在很长的一段时间里,我们的web服务器在遇到大规模流量访问的时候,很容易就把 CPU 负载飙到了 100%,导致响应速度过慢,用户体验卡顿,直到最近开启了Opcahe后,我们的QPS从200-300+,提升了1000+,响应速度也提高了很多,经过几天的摸爬滚打,终于有了一些些小小的经验,终于可以分享一下了。
在网上很多搜索Opcache配置优化的一些博客,很快就能获得一堆配置,但是是否真的适用于现在的项目规模和资源模式呢?对此下面将说明一些如何根据项目实际情况去优化opcache配置。
这是一段在网上推荐配置,下面我们尝试从实际出发来尝试调优这个配置。
opcache.enable=1 opcache.memory_consumption=512 opcache.interned_strings_buffer=64 opcache.max_accelerated_files=100000 opcache.validate_timestamps=1 opcache.revalidate_freq=60 opcache.save_comments=1 opcache.fast_shutdown=1
我的PHP实验环境为:PHP7.3,不同版本可能略有差异。
配置调整 && 优化
opcache.enable
opcache.enable
– 启用操作码缓存。如果禁用此选项,则不会优化和缓存代码。
所以我们需要设置为开启状态,才能启用到Opcache。
opcache.enable = 1
opcache.memory_consumption
opcache.memory_consumption
– OPcache 的共享内存大小,以兆(M)为单位。
它的默认值为64M,但是根据不同项目不同规模,都有不同的设置,我们可以使用 opcache_get_status
函数来查看Opcahce消耗了多少内存,是否根据需要增加内存,
在opcache_get_status
中提供内存消耗信息的是memory_usage
,值以字节为单位(byte)
"memory_usage": { "used_memory": 91647160, "free_memory": 440537232, "wasted_memory": 4686520, "current_wasted_percentage": 0.8729323744773865 },
我们计算 memory_consumption 的公式为: ( used_memory + free_memory + wasted_memory) / 1048576
那么这个配置的结果为: (91647160 + 440537232 + 4686520 ) / 1048576 = 512M
memory_consumption = 512M
interned_strings_buffer
interned_strings_buffer
– 用来存储预留字符串的内存大小,以兆字节为单位。
PHP使用了一种叫做字符串驻留(string interning)的技术来改善性能。例如,如果你在代码中使用了1000次字符串“aabbcccdd”,在PHP内部只会在第一次分配一个内存区域来储存该字符串,剩下的999次将使用内存指针来引用该字符串。
默认情况中,这个优化只会存在于单个PHP-FPM进程中,如果设置了这个选项,将会在所有 PHP-FPM 进程中共享。在比较大的项目中,这可以非常有效地节约内存,提高应用的性能。
该选项默认值为8MB,我们可以根据项目的规模和实际情况来调整这个数值。
opcache.interned_strings_buffer=8 opcache.interned_strings_buffer=16
opcache.max_accelerated_files
opcache.max_accelerated_files
– OPcache 哈希表中可存储的脚本文件数量上限。 真实的取值是在质数集合 { 223, 463, 983, 1979, 3907, 7963, 16229, 32531, 65407, 130987 } 中找到的第一个大于等于设置值的质数。 设置值取值范围最小值是 200,最大值在 PHP 5.5.6 之前是 100000,PHP 5.5.6 及之后是 1000000。
配置要保存在内存中的文件数,我们可以通过以下命令在获取整个项目中的php文件数。
find . -type f -print | grep php | wc -l
可以根据项目的文件数,在上面的 质数集合中选取 >= 的第一个质数。
我本地项目的运行结果为:
find . -type f -print | grep php | wc -l 18918
那么配置则为:
opcache.max_accelerated_files = 32531
opcache.validate_timestamps
opcache.validate_timestamps
启用此选项后,PHP将根据您的opcache.revalidate_freq
值检查文件时间戳,来确定是否需要重新生成PHP脚本编译缓存。
在生产环境模式中,如果项目流量比较高,请求比较密集,建议关闭此选项,以此来获得最高性能。
opcache.validate_timestamps = 0
设置关闭后,每次部署代码无法即时获得更新,需要重启php-fpm进程或者使用 kill -SIGUSR2 进行平滑重启,方可生效最新代码。
revalidate_freq
revalidate_freq
– 检查脚本时间戳是否有更新的周期,以秒为单位。 设置为 0 会导致针对每个请求, OPcache 都会检查脚本更新。如果 opcache.validate_timestamps
配置指令设置为禁用,那么此设置项将会被忽略。
在本地或开发环境开启Opcache我们可以设置为:
opcache.revalidate_freq = 0
小型流量服务端,可以设置为600s(10分钟),检查脚本更新
opcache.revalidate_freq = 600
大型及中型服务端建议设置 3600s 或 不做脚本更新检查,或者定时在流量低峰期做检查。
opcache.revalidate_freq = 3600
save_comments
save_comments
– 如果禁用,脚本文件中的注释内容将不会被包含到操作码缓存文件, 这样可以有效减小优化后的文件体积。 禁用此配置指令可能会导致一些依赖注释或注解的 应用或框架无法正常工作, 比如: Doctrine, Zend Framework 2 以及 PHPUnit。
如果项目中没有用到依赖注解等,可以将这个选项关闭,否者应开启。
fast_shutdown
fast_shutdown
– 如果启用,则会使用快速停止续发事件。 所谓快速停止续发事件是指依赖 Zend 引擎的内存管理模块 一次释放全部请求变量的内存,而不是依次释放每一个已分配的内存块。
从 PHP 7.2.0 开始,此配置指令被移除。 快速停止的续发事件的处理已经集成到 PHP 中, 只要有可能,PHP 会自动处理这些续发事件。
这个字配置会加快 php-fpm worker 进程回收,以便为下一个请求更快做好准备。
低于 PHP 7.2.0 需要手动开启。
opcache.fast_shutdown=1
最终我们优化调整后的位置如下,将它覆盖到php.ini,重载php-fpm进程即可生效。
opcache.enable=1 opcache.memory_consumption=512 opcache.interned_strings_buffer=64 opcache.max_accelerated_files=32531 opcache.validate_timestamps=0 opcache.save_comments=1 opcache.fast_shutdown=1
结尾
以上就是opcache部分配置优化策略,合理的使用OPcahce将会减少Web服务器的CPU使用率,但是会增加一定的内存使用率。如果使用得到,这将会大大提高或服务端和PHP的吞吐量。
最后补上开启OPcahe的优化后的效果图。