Composer默认重试间隔为渐进式延迟:首次100ms,后续增至500ms并保持;该机制仅作用于dist包下载,不延长单次请求超时,且2.1.x及更早版本会静默忽略--retries参数。

Composer默认重试间隔怎么算?
Composer对网络层错误(如CURL error 28超时、DNS失败、5xx响应)默认重试3次,但**不是固定间隔**,而是渐进式延迟:usleep(100000)(100ms)→ usleep(500000)(500ms)→ 第三次及以后仍为500ms。这个逻辑硬编码在CurlDownloader.php里,不随网络状况自适应。
关键点在于:它只控制“重试之间等多久”,**完全不延长单次请求的超时时间**。所以弱网下反复触发CURL error 28,加到--retries=10也没用——每次还是秒超时。
- 重试仅作用于dist包下载(zip/tar),对git clone、元数据请求(如provider-*.json)无效
- Composer 2.1.x及更早版本会静默忽略
--retries参数 - 验证是否生效:运行
composer install -vvv,看日志中是否有Retrying download字样
为什么指数退避比固定延迟更合理?
固定延迟(比如每次都等500ms)在抖动网络下容易引发雪崩:大量请求在同一时刻重试,把本就脆弱的镜像站打挂。而指数退避让重试时间随失败次数翻倍(1s → 2s → 4s → 8s),天然错峰。
但Composer原生不支持指数退避,它的wait_exponential是PHP生态外的方案(比如用tenacity写爬虫时)。你在Composer里只能靠COMPOSER_NETWORK_TIMEOUT拉长单次寿命,再配合有限重试来兜底。
围绕关键发现、作用机制、临床相关性及研究局限性展开讨论。适用于撰写或优化任何生物医学论文的“讨论(Discussion)”部分——包括结果解读、与既往文献关联、阐释意外发现、界定研究局限性,以及撰写结论。当用户输入以下任一指令时也会自动触发该功能: - “write my discussion” - “help me discuss my findings” - “how do I compare to prior studies” - “write the limitations par
- 真正起作用的是
COMPOSER_NETWORK_TIMEOUT=300(单位秒),它延长TLS握手、首字节等待、整个HTTP生命周期 -
http.timeout配置项等价于该环境变量,永久设置用composer config -g http.timeout 300 - 别设太高(如600),否则失败感知太慢,CI流水线卡住没人发现
镜像同步失败时,Composer会自动fallback吗?
不会。Composer遇到502/503/timeout/DNS失败,**直接报错退出,绝不尝试下一个镜像源**。它把repositories数组当查找顺序表,只在明确收到404时才查下一个;其他错误一律中断。
所以你配了多个镜像,却看到日志里反复请求同一个地址然后失败——这不是重试机制问题,是Composer压根没打算换源。
- 唯一可控的“fallback”是手动脚本:先
curl -I探测镜像健康状态,再用composer config -g repo.packagist切换 - 清缓存必须包含元数据目录:
rm -rf $(composer config --global cache-dir)/repo/https---mirrors-aliyun-com-composer,否则坏缓存会掩盖真实网络问题 - URL末尾缺
/会导致路径拼接错误(如composerpackages.json),返回404后Composer静默回退到packagist.org,连日志都不提醒
重试和超时参数如何协同生效?
它们管的是不同阶段:--retries决定“失败后重来几次”,COMPOSER_NETWORK_TIMEOUT决定“每次重来最多忍多久”。两者必须配合,单独调高任一个都没意义。
典型弱网场景下,你应该优先调高超时值,再确认重试次数够用。国内常见NAT超时是120–180秒,所以COMPOSER_NETWORK_TIMEOUT=240是较稳妥的起点。
- 临时生效:
COMPOSER_NETWORK_TIMEOUT=240 composer install - 永久生效:
composer config -g http.timeout 240(注意不是http-timeout) - IPv6不稳定时加
CURL_IPRESOLVE=4强制走IPv4,避开某些ISP的路由黑洞 - 如果仍卡在
Downloading (0%),大概率是镜像源本身不可达,不是参数问题

















