PHP Opcache 配置优化实战

17ns

前言

起源:在很长的一段时间里,我们的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的优化后的效果图。

image

阅读 1.8k

Bug总工程师

257 声望
14 粉丝
0 条评论
你知道吗?

Bug总工程师

257 声望
14 粉丝
宣传栏