不会停机但会不可靠;composer update 直接修改 vendor/ 导致类加载混乱,需用符号链接切换原子发布,配合动态 autoload 路径与隔离运行时文件。

Composer update 会停机吗?
不会自动停机,但默认行为会让应用在更新窗口内不可靠——composer update 直接修改 vendor/ 目录,如果正在运行的 PHP 进程恰好加载了旧版类、又在更新中途被新请求触发 autoload 查找新路径,就可能报 Class not found 或加载混杂版本。这不是 Composer 的 bug,而是共享文件系统 + 运行时热加载的天然冲突。
- PHP-FPM / Apache mod_php 等常驻进程模型下,
vendor/被改写时,已加载的类定义不会刷新,但新请求可能命中刚写了一半的新文件 -
composer install同样有风险,只要它清空并重建vendor/ - 真正安全的前提是:更新期间所有 PHP 进程都用同一套完整、未中断的
vendor/快照
用符号链接切换 vendor 实现原子发布
核心思路是把 vendor/ 变成指向带时间戳或哈希后缀的实际目录的软链,更新时先构建全新副本,再用 ln -sf 原子替换链接。Web 服务器和 PHP 进程只认链接名,切换瞬间完成,无中间态。
- 每次部署前执行:
composer install --no-dev --optimize-autoloader到新目录,如vendor-20241105-abc123 - 确保
autoload.php路径不硬编码,统一通过dirname(__DIR__) . '/vendor/autoload.php'动态加载 - 切链命令必须用
-f(强制)且不带空格:ln -sf vendor-20241105-abc123 vendor,避免残留旧链接 - Nginx/Apache 需确认未开启
enable_dl或动态扩展加载,否则扩展.so 文件也可能被并发覆盖
为什么不能只靠 opcache_reset()?
清 opcache 只解决已加载类的内存缓存问题,不解决文件系统层面的竞态。即使调用了 opcache_reset(),PHP 进程仍可能在 unlink/rename 过程中读到截断的文件、找不到 classmap 中的路径,或因 realpath cache 未刷新而继续访问旧 vendor/ 下的文件。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
-
opcache.revalidate_freq=0和realpath_cache_ttl=0在生产环境会严重拖慢性能,不推荐作为零停机方案 -
opcache_invalidate()无法批量清理所有 vendor 文件,且对 require_once 的非类文件无效 - 真正要隔离的是整个
vendor/目录的生命周期,不是单个 opcode 缓存项
CI/CD 流水线里怎么安全跑 composer update?
流水线本身不直接更新线上 vendor/,而是生成可验证的部署包。关键动作必须在构建阶段完成,而非上线时临时执行。
- CI 中用
composer update --dry-run检查变更是否符合预期,再执行真实安装到独立构建目录 - 生成部署包时,把
vendor/目录整体打包(或上传至对象存储),而非只传composer.lock - 上线脚本里禁止出现
composer install,只做解压 + 切链接 + 清理旧目录(延迟删除,比如保留最近两个版本) - 如果项目用了
composer bin或插件,确认它们的二进制文件也随 vendor 一起被复制,而不是全局安装
最易被忽略的一点:vendor/ 下的某些包会写入运行时文件(如 doctrine/cache 的文件缓存、monolog 的日志轮转),这些路径若基于 __DIR__ 构造,就会随着 vendor 切换而指向不同物理位置。得统一配置为绝对路径,且指向 /var/www/shared/ 类的跨版本共享目录。










