问题背景
随着研发团队不断扩大Artifactory中Maven仓库也在逐步增多,包括 local、remote、virtual 仓库,其中往往会涵盖RELEASE和SNAPSHOT包类型仓库,为了对使用客户透明简化用户配置,管理人员会通过创建一个virtual仓库,将所有用到的 local(RELEASE和SNAPSHOT)、remote(RELEASE和SNAPSHOT) 包含到一个virtual 仓库中。这样让客户统一使用 virtual 仓库,虽然最大程度上节约了用户在修改配置的成本,但是也会出现一个致命的问题,拉包速度降低,极端情况下甚至几Byte/秒的速度。
分析原因
上面说了所有仓库组合起来之后,会出现拉包速度降低的问题,那么为什么会出现拉包慢的情况呢?
首先,Maven在解析 SNAPSHOT依赖包时,会在 virtual 仓库中所有的 remote仓库中遍历下载本次依赖包的 maven-metadata.xml 文件,这样做的目的是为了保持与远端仓库的强一致性,因为SNAPSHOT更新迭代较快。
其次,Artifactory 对所有 maven-metadata.xml 进行聚合,并找到 latest 版本返回给客户。
那么,如果一个 virtual 仓库中包含 10 个 remote仓库,则本次通过 gavc 解析一个依赖包需要下载 maven-metadata.xml 10次并进行聚合,相对于一个 virtual 仓库下只有2、3个 remote类型的仓库来说,时间消耗增大了 4~5 倍。这也就是仓库包含的说下载一个包大量的时间都额外消耗在了更新和聚合maven-metadata.xml上。这也就是常见的拉包慢问题的主要原因。
当然拉包慢也不全是这个问题,也有可能是网络或者磁盘速写速度等问题造成的,这个就不在这里过多赘述了。
解决方案
1. release 和 snapshot 仓库分离:
设置三个virtual repository
(1)第一个 maven-snapshot-virtual include 所有maven-snapshot-local
(2)第二个 maven-release-virtual include 所有maven-release-local
(3)第三个 maven-remote-virtual include 所有remote repository
其中remote virtual 仓库只包含release 类型的远程仓库,如需snapshot,加到第一个virtual仓库中通过Artifactory set me up生成的setting.xml,选择 maven-snapshot-virtual和maven-release-virtual
在生成后的setting.xml,中添加maven-remote-virtual 相关配置,并且disable remote-virtual
2.减少 virtual 中 remote 仓库数量
前面说了拉包慢的原因,是因为下载一个包大量的时间都额外消耗在了更新和聚合maven-metadata.xml上,那么我们降低remote仓库的数量后,可以直接减少下载 maven-metadata.xml次数,降低在下载和聚合时所消耗的时间。
3. 控制SNAPSHOT包的数量
在仓库中配置存储的 SNAPSHOT版本数量(默认存储数量不限),控制在指定数量内。比如配置5个那么在仓库中每个SNAPSHOT版本的包最多只有5个,这样在聚合maven-metadata.xml文件时,聚合文件的运算量也将有所下降,提升聚合所消耗的时间。
4. 定时清理SNAPSHOT包
可以定时清理SNAPSHOT包,减少包的数量,原因与第三点相同,就是减少包的数量,降低聚合的时间,提升拉包效率。
清理方法可以使用AQL进行清理,清理示例如下:
(1)maven-test-local 仓库的 test/version 下有5个 snapshot 包:
(2)编写AQL清理脚本(保留 3 个最新版本【snapshot-v3.jar、snapshot-v4.jar、snapshot-v5.jar】,清除其余 maven-test-local 仓库 test/version 路径下的 snapshot 包):
(3)使用 JFrog CLI 执行清理命令(--quiet:跳过删除确认消息,调试脚本阶段建议去掉此参数):
jfrog rt del --quiet --spec=delete.json
5. 指定依赖解析路径:
如本项目只使用特定路径(com/apache/*)的依赖包,添加多个路径点击“⊕”,仓库参考配置如下:
如本项目使用除了特定路径(com/apache/*)的其他依赖包,添加多个路径点击“⊕”,仓库参考配置如下: