PHP-FPM 容器内无法加载改动后的代码

环境

  • Docker 19.03.5
  • PHP-FPM 7.1.33
  • Deployer 6.8.0

描述

触发 CI Pipeline 后,执行 deployer 进行部署,一切顺利,目录结构如下:

.
├── current -> releases/22 # 当前运行的版本,Nginx 和 PHP 都指向该软链
├── releases
│   ├── 20
│   ├── 21
│   └── 22
└── shared
    └── storage

7 directories, 0 files

21 这个文件夹上个发布的版本,22 是最新发布的版本,但是请求项目页面,显示的还是 20 里面的代码逻辑。于是我执行如下命令:

mv 21 temp

此时再去请求项目,则代码加载的是最新的 22 这个目录下的。

一开始考虑到 Docker volume 的缓存问题,所以在宿主机和容器(Nginx 和 PHP-FPM)中都进行 current 软链的信息比对,发现都是一致的,那么也就排除了是因为挂载卷导致的文件系统缓存问题。

然后我手动模拟发版的操作,执行了如下命令:

ln -nfs --relative /usr/wwwroot/internal/releases/21 /usr/wwwroot/internal/release # 创建最新版本的软链接,用于安装依赖
mv -T /usr/wwwroot/internal/release /usr/wwwroot/internal/current # 将安装好的项目软链修改为当前版本

按理来说此时加载的应该是上一版本的代码,但是实际请求发现代码逻辑是 22 那个目录下的。这次我重启了 PHP-FPM 的容器,发现又正常回滚到 21 的代码了。那么问题就存在 PHP-FPM 容器中。

然后按照网上的方法,禁用了 Opcache 以及清理了 realpath_cache,重启 PHP-FPM,再次将 current 软链到 releases/20 这个目录,发现依旧不能生效。

我能想象到的可能产生缓存的地方就这些了,各位有遇到过类似问题的吗?还请赐教,不胜感激!

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
最佳答案

最后确定是 PHP 的 realpath_cache 导致软链切换后读取的依然是旧代码,总结方案如下:

1、等待 realpath_cache 过期,默认 120 秒(因为realpath_cache 是作用于单个 PHP 进程的,所以各进程之间加载新代码的时间无法保证一致);

2、重启PHP-FPM;

3、mv 修改上一版项目名称或路径(让缓存失效);

3年前 评论
xing393939 3年前
GeorgeKing (作者) (楼主) 3年前
讨论数量: 2

软链接后直接docker exec到容器中看对应目录的代码是否变化。 如果没有软链接,改动代码,容器中的代码肯定是变化的,软链接的形式我还没有弄过。

3年前 评论
GeorgeKing (楼主) 3年前

最后确定是 PHP 的 realpath_cache 导致软链切换后读取的依然是旧代码,总结方案如下:

1、等待 realpath_cache 过期,默认 120 秒(因为realpath_cache 是作用于单个 PHP 进程的,所以各进程之间加载新代码的时间无法保证一致);

2、重启PHP-FPM;

3、mv 修改上一版项目名称或路径(让缓存失效);

3年前 评论
xing393939 3年前
GeorgeKing (作者) (楼主) 3年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!