“extracting archive”卡住不是网络问题,而是磁盘i/o瓶颈所致,主因是文件系统调用延迟、inode耗尽或容器挂载方式不当,需优化缓存路径、禁用vendor挂载并调整ci构建参数。

为什么“Extracting archive”卡住不是网络问题
Composer install 卡在 Extracting archive 阶段,带宽跑不满、CPU 占用低,但耗时飙升——这不是网络慢,是磁盘 I/O 已被压垮。解压 ZIP 包时密集调用 stat、mkdir、file_put_contents,尤其在 macOS APFS、Windows NTFS 或 CI 挂载卷上,毫秒级系统调用延迟会被放大成秒级阻塞。
常见错误现象包括:No space left on device(但 df -h 显示空间充足)、failed to open stream、反复重试下载;根本原因常是 inode 耗尽(df -i 显示 100%),或挂载桥接层引入的文件系统转发开销。
Docker/CI 中必须禁用 vendor 目录挂载
把 vendor/ 直接挂载进容器(如 -v $(pwd)/vendor:/app/vendor)是最典型的 I/O 陷阱。宿主机与容器间所有 openat、write 操作都需跨层桥接,在 macOS/Windows 或 GitHub Actions runner 上极易堆积等待。
- 开发中改用命名卷:
docker run -v $(pwd):/app -v composer-vendor:/app/vendor image composer install - CI 构建时严禁在宿主机执行
composer install后拷贝vendor/;必须在容器内完成安装 - 若需同步输出,用
rsync -av --delete --exclude='.git' vendor/ $CI_PROJECT_DIR/vendor/,避免cp -r或tar触发全量stat扫描
cache-dir 必须脱离慢盘,优先移至 tmpfs
~/.composer/cache 默认落在用户主目录,若该路径位于机械硬盘、网络存储、加密卷或 Docker overlay2 层,ZIP 校验和解压前的随机读会直接拖垮速度。实测从 SSD 迁移到 tmpfs 后,Extracting archive 阶段耗时下降 60%+。
- 查当前路径:
composer config -g cache-dir - Linux CI runner 上创建内存盘:
sudo mount -t tmpfs -o size=2G tmpfs /mnt/ramdisk,再设缓存路径:composer config -g cache-dir /mnt/ramdisk/composer-cache - 别设为
/tmp:某些 CI 平台(如 AWS CodeBuild)会定期清空,导致缓存反复重建
生产构建必须绕过 autoload 和脚本生成
并发下载快了,但 Generating autoload files 和 post-install-cmd 仍是单线程重负载。一个含 200+ 包的项目,这部分可占总耗时 35% 以上,且不受益于任何并发参数。
- CI 构建命令必须带:
composer install --no-dev --prefer-dist --optimize-autoloader --classmap-authoritative --no-autoloader --no-scripts - 后续单独补 autoload:
composer dump-autoload --optimize --classmap-authoritative - 漏掉
--classmap-authoritative,autoload 仍会 fallback 到 PSR-4 路径拼接,每次类加载都触发file_exists()和stat()











