折磨人的 OPCache
背景
一切源于同一份代码在开发机(云主机)中和测试环境(k8s容器)中运行的结果相关很大。如下图:左边是云主机,右边是优化前的 k8s 容器。

是何原因导致?刚开始找我查这个问题时也是一脸的懞。先说下我的怀疑路径:
- 代码有问题(新开发的框架);
- 环境配置有问题;
- 引用的包有问题;
- OPCache 配置有问题;
- ......
怀疑的过程就是一一验证的过程,本文将一点一点的介绍我使用哪些工具,如何验证等等!
小心求证
框架已较优秀
本司的框架是基于 Lumen8 进行迭代的,优化的点是:
- 废弃了 .env 文件,因为每次请求会读取 .env 内容然后解析,这操作过程是有 I/O 过程的,此优化是本人在之前推进完成(后续会推出相关内容);
- 路由的优化。
刚开始听说框架是新开发的,自然也就怀疑相关调整是否有误?于是本人就在开发环境搭建了性能分析的平台
tideway_xhprof + xhgui
来一探究竟。起初的结果也是一个乌龙。因为分析后出现了大量的
Composer\Autoload\includeFile@1
及相关错误,怀疑了下是不是因为框架的规范不完善导致的 OPCache
失效。耽误了一点时间才想起,本人开发环境是为了适配新的框架对 php
版本的要求,重新装的新版本,OPCache
就没打开,开启后结果就达到上图左侧效果了。(不够严谨的作者,该批!)
环境已成模板
框架不是问题,接下来的怀疑点就是环境上了。通过 php -i
and php -m
等命令对环境配置做了很多确认,毫无收获。甚至把新、老版本的代码放一起进行压测比较。老版本的代码是没有任何问题的。说明不是环境问题了。
接下的时间又进行了很多其它的验证,均无收获!
锁定 OPCache
因为在测试环境的结果就与上图右侧结果一致(不好在测试环境搭建性能分析平台),所以大胆的猜测了下是
OPCache 未生效。所以开始时用了入侵式的方案,在入口处增加了
var_dump(opcache_get_status());die;
代码进行对比,发现测试环境的结果中 scripts
一项未出现任何开源的包,只出现了业务代码与内部包。多次调整代码,发现入侵式的
OPCache 信息查阅很不友好。幸亏马上就查到 CacheTool
这一非入侵式的工具,为后续的排查带来质的飞越。
通过在两个环境运行如下命令非常确定的是非私有包都未被加载到 cache 中。
1 |
|
那么,到此为止,一切的问题就变成了为什么 OPCache 在容器中对开源包不生效的问题了?
拨开云雾见真经
在确定了 OPCache 不生效只针对开源项目的包,还折腾了很久......
后来一个无意间的小操作发现了问题所在,在怀疑是否文件有问题时
ls -al
了下文件,发现居然是 2022 年 9 月 22
一个未来时间。虽然没有第一时间去查阅为啥都以 OPCache
对未来时间不生效,但是为了快速确定是否有影响,本人修改文件的时间再次验证:
1 |
|
修改完时间后再次执行代码,发现已经能通过 cachetool 看到相应的缓存脚本了。那接下来就是验证结论的时刻。
1 |
|
再次运行压测,然后就一切正常了。那接下来问题就变成了两个:运维确定因啥时间会变成未来时间? & OPCache 使用哪个时间及怎么判断时间了?
针对时间问题,本人翻阅了下 php 源码中 OPCache 相关代码,可以确定是使用了 st_mtime。
1 |
|