maven为什么只连接第一个mirror ?

网上说,如果第一个Mirror能下载到,就不访问其他mirror。但是实验发现,第一个下载不到依赖,也不会访问其他的。实验中断开网络,在项目根下执行命令 mvn dependency:resolve 即可观察访问哪个

<mirrors>
    <mirror>
      <id>ab</id>
      <mirrorOf>central</mirrorOf>
      <name>Nexus aliyun</name>
      <url>url 1</url>
    </mirror>

<mirror>
      <id>cd</id>
      <mirrorOf>*</mirrorOf>
      <name>Nexus aliyun</name>
      <url>url 2</url>
    </mirror>
  </mirrors>

又发现只有增加2个条件才能轮询每个Mirror:一是pom中写一个repository。二是第一个mirror的id必须叫1st
此时maven就会轮询每个Mirror查找,而且并不访问pom中的repository地址

阅读 870
1 个回答

Maven的镜像(Mirror)配置行为确实有些让人困惑。根据您的实验和描述,我来解释Maven镜像配置的工作原理:

Maven镜像选择的核心规则是基于mirrorOf标签的匹配规则:

  1. 镜像优先级: Maven会按照mirrors配置中的顺序依次检查每个镜像,第一个匹配的镜像会被使用。
  2. mirrorOf匹配规则:

    • central: 只匹配中央仓库
    • *: 匹配所有仓库
    • *,!repo1: 匹配除repo1外的所有仓库

在您的配置中:

<mirror>
  <id>ab</id>
  <mirrorOf>central</mirrorOf>
  <url>url 1</url>
</mirror>

<mirror>
  <id>cd</id>
  <mirrorOf>*</mirrorOf>
  <url>url 2</url>
</mirror>

Maven的行为是这样的:当寻找依赖时,它首先检查匹配的仓库。如果依赖是从中央仓库请求的,第一个镜像ab会匹配(因为mirrorOf=central),Maven就只会尝试从url 1下载。如果该URL不可用,Maven默认不会自动尝试下一个镜像,而是报错。

您观察到的特殊情况:

  1. 当镜像ID为"1st"时行为不同
  2. 在POM中添加repository时行为不同

这可能与Maven的某些特殊处理或版本特性有关。Maven默认行为确实是只尝试匹配的第一个镜像,不会自动轮询。

解决方案:

  1. 使用仓库组: 如果您希望Maven能够在一个镜像失败时尝试另一个,最好使用Nexus或Artifactory等仓库管理器设置仓库组。
  2. 按照特定性排序镜像:

    <mirrors>
      <!-- 特定仓库的镜像先列出 -->
      <mirror>
     <id>specific-repo-mirror</id>
     <mirrorOf>specific-repo</mirrorOf>
     <url>url-for-specific</url>
      </mirror>
      
      <!-- 通用镜像放在最后 -->
      <mirror>
     <id>all-repos-mirror</id>
     <mirrorOf>*</mirrorOf>
     <url>fallback-url</url>
      </mirror>
    </mirrors>
  3. 使用高级镜像选择器:Maven 3.8.0及以上版本支持更灵活的镜像选择器配置。

Maven的这种行为主要是为了性能和确定性考虑,确保依赖解析过程是可预测的,而不是自动轮询尝试多个镜像。