Composer 不支持 repo.packagist 多域名备用,后设覆盖前设;repositories 多源仅对 404 fallback,网络错误即中断;可靠容灾需脚本探测可用镜像并切换配置+清缓存。

composer config -g repo.packagist 只能设一个 URL,多域名不是“备用”而是覆盖
Composer 根本不支持在 repo.packagist 字段里填多个域名,比如 https://mirrors.aliyun.com/composer/ https://mirrors.ustc.edu.cn/composer/。你执行两次 composer config -g repo.packagist,后一次会直接抹掉前一次——它底层就是一个字符串字段,不是数组,也不是 fallback 列表。官方明确拒绝加入该功能(GitHub issue #8729),这不是 bug,是设计。
项目级 repositories 数组不解决 DNS 或超时类故障
有人试图在 composer.json 的 repositories 里写多个镜像源,指望“一个挂了走下一个”。但实际行为非常苛刻:
- 只有前一个源返回 HTTP 404(包确实不存在)时,Composer 才查下一个
- DNS 解析失败、连接超时、502、503 等网络错误,全部直接中断,不会 fallback
- 必须显式写
{"packagist.org": false}在数组第一项,否则 Composer 仍偷偷连官方站 - 所有镜像项都得是
"type": "composer",URL 末尾必须带/,否则请求路径错位导致 404
真正可用的多域名容灾:靠外部脚本探测 + 切换 + 清缓存
可靠方案不是让 Composer 自己选,而是由你控制流程:
- 用
curl -I --max-time 3 https://mirrors.aliyun.com/composer/packages.json探测可用性,检查状态码是否为 200 - 按优先级顺序试几个镜像(阿里云 → 腾讯云 → 中科大 → 官方),第一个成功就
composer config -g repo.packagist composer <url> - 切换后必须执行
composer clear-cache,否则旧元数据缓存还在,请求仍发往已失效地址 - CI 流水线中建议把这套逻辑封装成 shell 函数或 Makefile target,避免每次重写
插件方案(如 composer-plugin-mirror)有隐性限制
虽然 yunwuxin/composer-plugin-mirror 支持配置多个镜像并自动 fallback,但它依赖 repositories 键名排序(字母序),且要求每个镜像都声明 "packages": ["*"]。问题在于:
- Composer 3.x+ 的元数据请求(
packages.json、provider-*.json)根本不走repositories数组,只认repo.packagist配置 - 插件只能干预 ZIP 包下载阶段,对元数据拉取无能为力
- 若镜像站尚未同步你要的 provider 文件(比如
p2/laravel/framework/13.2.0.json),插件 fallback 也无效——它没东西可下
最易被忽略的一点:镜像同步是按需触发的,不是全量实时同步。你以为配了阿里云就万事大吉,结果它还没拉到 Laravel 13.2.0 的 provider 文件,而中科大镜像恰好已有——这时候手动切源比等插件 fallback 更快更确定。


















