Composer重试机制仅作用于HTTP下载阶段,对git clone等操作无效;--retry需配合http.timeout、process-timeout及缓存清理协同生效,且依赖镜像源稳定性与DNS正确性。

Composer 本身不处理“间歇性断开”的底层重连,它依赖 cURL 和 PHP 的网络层;真正起作用的是重试策略 + 超时控制 + 缓存规避,三者缺一不可。
为什么 --retry 参数经常没用?
因为 --retry(或 --retries)只对 HTTP 下载阶段生效,且仅在明确识别为可恢复错误时才触发——比如 CURL error 28(超时)、CURL error 6(DNS 失败)、5xx 响应。但它不会重试 git clone、svn export 或本地解压失败这类操作。
-
--retry=3只影响 dist ZIP 包下载,对 VCS 包(如"type": "vcs")完全无效 - 如果错误是
Content-Length mismatch,说明缓存文件已损坏,重试只会反复读坏文件,必须先composer clear-cache - 某些镜像源返回
302重定向后又断开,cURL 默认不自动跟随重试,需确保http.keepalive=true
process-timeout 和 http.timeout 的实际作用差异
这两个配置常被混用,但控制的是完全不同的环节:
-
process-timeout:限制单个外部命令(如git clone、unzip)的最大运行秒数,默认300。间歇性断开导致git卡住时,它才是救命项 -
http.timeout:限制单次 HTTP 请求的 socket 等待时间,默认600。它管的是cURL连接建立和响应头接收,不包括大包体传输耗时 - 真正影响大 ZIP 传输的是 PHP 的
default_socket_timeout(php.ini),建议设为30~60,否则可能卡在“Downloading xxx.zip”长达数小时
换源不是万能的,但必须做对顺序
国内用户遇到间歇性断开,90% 是因为直连 packagist.org 触发了中间链路抖动。但盲目换源反而会引入新问题:
- 优先用阿里云镜像:
composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/,它同步延迟低、CDN 节点稳定 - 避免使用已停用源(如
https://packagist.phpcomposer.com),会导致404后无限重试 - 若项目中硬编码了
repositories,全局镜像会被忽略——必须检查composer.json里是否含"packagist.org": false或自定义packages条目 - 私有 Git 仓库(
github.com、gitlab.company.com)不受镜像影响,需单独配http-proxy或改用 HTTPS + PAT token
缓存目录预填充比调参数更治本
当网络持续抖动时,靠重试和延时只是“等它变好”;而把包提前放进缓存,能让 Composer 完全跳过下载阶段:
- 确认缓存路径:
composer config --global cache-dir,通常是~/.composer/cache - 手动下载对应包的 ZIP(从
composer.lock中取dist.url),解压后放入files/vendor/name/hash/子目录 - 运行
composer install --no-interaction --prefer-dist --no-plugins,它会校验 hash 并直接复制,不发任何网络请求 - CI 环境中可把
~/.composer/cache挂载为持久卷,避免每次重建缓存
最易被忽略的一点:Composer 的重试逻辑不感知 DNS 变更。如果本地 DNS 缓存污染或 /etc/hosts 临时映射失效,即使开了重试,所有请求仍会卡在解析阶段——此时 dig packagist.org 和清系统 DNS 缓存比调 retries 更有效。


















