有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java如何高效地处理maven3时间戳快照?

既然maven-3为<;独一无二>;假</独一无二>;对于快照人工制品,似乎确实需要使用带时间戳的快照。特别是内部使用maven 3的m2eclipse似乎受到了影响,当快照不是唯一的时,更新快照不起作用

似乎最好将所有快照设置为uniqueVersion=false

现在,切换到时间戳版本似乎没有什么大问题,毕竟它们是由一个中央nexus存储库管理的,该存储库能够在定期间隔内删除旧的快照

问题在于本地开发人员工作站。他们的本地存储库确实快速增长,并拥有独特的快照

如何处理这个问题

现在我看到了以下可能的解决方案:

  • 要求开发人员定期清理存储库(这会导致大量的融合,因为删除需要很长时间,下载所需的所有内容需要更长时间)
  • 设置一些脚本,从本地存储库中删除所有快照目录,并要求开发人员不时运行该脚本(比第一个脚本更好,但运行和下载当前快照仍需要相当长的时间)
  • 使用dependency:purge local repository插件(从eclipse运行时确实有问题,因为打开了文件,需要从每个项目运行)
  • 在每个工作站上设置nexus,并设置一个清理旧快照的作业(最好的结果,但我不想维护50多台nexus服务器,而且开发人员工作站上的内存总是很紧)
  • 停止使用快照

防止本地存储库填满硬盘空间的最佳方法是什么

更新:

为了验证beaviour并提供更多信息,我设置了一个小型nexus服务器,构建两个项目(a和b),然后尝试:

a:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>de.glauche</groupId>
  <artifactId>a</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <distributionManagement>
    <snapshotRepository>
        <id>nexus</id>
        <name>nexus</name>
        <url>http://server:8081/nexus/content/repositories/snapshots</url>
    </snapshotRepository>
  </distributionManagement>

</project>

b:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>de.glauche</groupId>
  <artifactId>b</artifactId>
  <version>0.0.1-SNAPSHOT</version>
    <distributionManagement>
    <snapshotRepository>
        <id>nexus</id>
        <name>nexus</name>
        <url>http://server:8081/nexus/content/repositories/snapshots/</url>
    </snapshotRepository>
  </distributionManagement>
 <repositories>
    <repository>
        <id>nexus</id>
        <name>nexus</name>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
        <url>http://server:8081/nexus/content/repositories/snapshots/</url>
    </repository>
 </repositories>
  <dependencies>
    <dependency>
        <groupId>de.glauche</groupId>
        <artifactId>a</artifactId>
        <version>0.0.1-SNAPSHOT</version>
    </dependency>
  </dependencies>
</project>

现在,当我使用maven并在“a”上运行“deploy”时,我将

a-0.0.1-SNAPSHOT.jar
a-0.0.1-20101204.150527-6.jar
a-0.0.1-SNAPSHOT.pom
a-0.0.1-20101204.150527-6.pom

在本地存储库中。每次运行部署目标时都会使用新的时间戳版本。当我尝试从nexus服务器更新快照时也会发生同样的情况(关闭“a”项目,从本地存储库中删除它,构建“b”)

在一个构建了大量快照的环境中(想想哈德逊服务器…),本地reposioty充满了旧版本fast

更新2:

为了测试失败的方式和原因,我又做了一些测试。每个测试都针对clean everything运行(de/glauche从机器和nexus中删除)

  • 使用maven 2.2.1部署mvn:

计算机A上的本地存储库不包含快照。jar+快照时间戳。罐子

但是:nexus中只有一个带时间戳的jar,元数据显示:

<?xml version="1.0" encoding="UTF-8"?>
<metadata>
  <groupId>de.glauche</groupId>
  <artifactId>a</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <versioning>
    <snapshot>
      <timestamp>20101206.200039</timestamp>

      <buildNumber>1</buildNumber>
    </snapshot>
    <lastUpdated>20101206200039</lastUpdated>
  </versioning>
</metadata>
  • 在m2eclipse(嵌入式m3最终版)中运行更新依赖项(在机器B上)>;本地存储库有快照。jar+快照时间戳。罐子:(
  • 使用外部maven 2.2.1运行包目标->;本地存储库有快照。jar+快照时间戳。罐子:(

好的,下一次尝试maven 3.0.1(删除项目a的所有痕迹后)

  • 机器A上的本地存储库看起来更好,只有一个无时间戳的jar

  • nexus中只有一个带时间戳的jar,元数据显示:

    德格拉切 A. 0.0.1-SNAPSHOT

    <snapshot>
      <timestamp>20101206.201808</timestamp>
      <buildNumber>3</buildNumber>
    </snapshot>
    <lastUpdated>20101206201808</lastUpdated>
    <snapshotVersions>
      <snapshotVersion>
        <extension>jar</extension>
        <value>0.0.1-20101206.201808-3</value>
        <updated>20101206201808</updated>
      </snapshotVersion>
      <snapshotVersion>
        <extension>pom</extension>
        <value>0.0.1-20101206.201808-3</value>
        <updated>20101206201808</updated>
      </snapshotVersion>
    </snapshotVersions>
    

  • 在m2eclipse(嵌入式m3最终版)中运行更新依赖项(在机器B上)>;本地存储库有快照。jar+快照时间戳。罐子:(

  • 使用外部maven 2.2.1运行包目标->;本地存储库有快照。jar+快照时间戳。罐子:(

综上所述:maven3中的“部署”目标比2.2.1中的效果更好,创建机器上的本地存储库看起来不错。 但是,接受者总是会得到很多时间限制的版本

我该怎么办怎么了

更新3

我还测试了其他各种配置,首先用artifactory替换nexus->;同样的行为。然后使用linux maven 3客户端从存储库管理器下载快照->;本地存储库仍有时间戳快照:(


共 (6) 个答案

  1. # 1 楼答案

    我不喜欢任何提议的解决方案。删除maven缓存通常会显著增加网络流量并减慢构建过程。build helper maven插件只对一个工件有帮助,我想要一个解决方案,可以用一个简单的命令从本地缓存中清除所有过时的时间戳快照工件。经过几天的搜索,我放弃了,决定写一个小程序。最后一个项目似乎在我们的环境中运行得很好。所以我决定与其他可能需要这种工具的人分享。可以从github获取源:https://github.com/nadestin/tools/tree/master/MavenCacheCleanup

  2. # 2 楼答案

    应用于(通过mvn部署)部署到Nexus等Maven存储库的工件的<uniqueVersion>配置

    要从Nexus中删除这些内容,您可以轻松创建一个自动作业,每天清除快照存储库。可以将其配置为保留一定数量的ShapShot,或将其保留一段时间。它非常简单,效果非常好

    开发人员机器上本地存储库中的工件从“安装”目标到达那里,并且不使用这些时间戳。。。他们只会不断替换唯一的快照版本,除非您也在增加版本号(例如,1.0.0-SNAPSHOT到1.0.1-SNAPSHOT)

  3. # 3 楼答案

    至于远程存储库这一部分,我认为前面讨论定期清除快照的答案是可行的。但是没有人解决您问题中的本地开发人员工作站同步部分

    我们还没有开始使用Maven3,所以我们还没有看到快照开始在本地机器上构建

    但我们在m2eclipse上遇到了不同的问题。当我们启用了“工作区解析”并且项目存在于我们的工作区中时,源代码更新通常会使我们处于最前沿。但我们发现很难让m2eclipse用Nexus中最近发布的工件来更新自己。我们的团队中也遇到了类似的问题,问题尤其严重,因为我们有一个非常大的项目图。。。有很多依赖项不会出现在您的工作区中,但会频繁发布快照

    我敢肯定,这可以归结为m2eclipse中的一个问题,即它没有完全按照应该的方式处理快照。您可以在eclipse中的Maven控制台中看到,m2eclipse告诉您它正在跳过最近发布的快照的更新,因为它有一个缓存版本。如果从运行配置或命令行执行-U操作,Maven将获取元数据更改。但是“更新快照…”选择应该告诉m2eclipse让Maven终止这个缓存。它似乎没有被传递出去。如果你有兴趣投票支持它,这里似乎有一个bug: https://issues.sonatype.org/browse/MNGECLIPSE-2608

    你在某个地方的评论中提到了这一点

    对于这个问题,最好的解决办法似乎是让开发人员在Eclipse内部出现故障时清除他们的本地工作站。不同问题的类似解决方案。。。其他人报告了支持m2eclipse的Maven 2.2.1和3的问题,我也看到了同样的情况

    如果您使用的是Maven3,我希望您可以将其配置为只提取最新的快照,并将其缓存到存储库指定的时间(或手动使其过期)。希望您不需要在本地存储库中存储大量快照

    除非你说的是一个构建服务器,它在它们上面手动执行mvn install。至于如何防止快照在生成服务器这样的环境中生成,通过让每个构建使用自己的工作区和本地存储库(尽管在Maven 2.2.1中,POM之类的某些东西似乎总是从~/.m2/存储库中出现),我们在某种程度上躲过了这一难题。额外的快照实际上只在单个构建中存在,然后它们会被删除(并从头开始重新下载)。我们已经看到,这种方法一开始确实会占用更多的空间,但它往往比在单个存储库中解决所有问题更稳定。这个选项(在Hudson上)被称为“使用私有Maven存储库”,当您选择使用Maven构建时,它位于项目配置构建部分的高级按钮下。以下是该选项的帮助说明:

    Normally, Hudson uses the local Maven repository as determined by Maven — the exact process seems to be undocumented, but it's ~/.m2/repository and can be overridden by in ~/.m2/settings.xml (see the reference for more details.) This normally means that all the jobs that are executed on the same node shares a single Maven repository. The upside of this is that you can save the disk space, but the downside of this is that sometimes those builds could interfere with each other. For example, you might end up having builds incorrectly succeed, just because your have all the dependencies in your local repository, despite that fact that none of the repositories in POM might have them.

    There are also some reported problems regarding having concurrent Maven processes trying to use the same local repository.

    When this option is checked, Hudson will tell Maven to use $WORKSPACE/.repository as the local Maven repository. This means each job will get its own isolated Maven repository just for itself. It fixes the above problems, at the expense of additional disk space consumption.

    When using this option, consider setting up a Maven artifact manager so that you don't have to hit remote Maven repositories too often.

    If you'd prefer to activate this mode in all the Maven jobs executed on Hudson, refer to the technique described here.

    希望这能有所帮助——如果不能解决你的问题,请让我知道我错过了什么

  4. # 4 楼答案

    在groovy中,删除像artifact-0.0.1-20101204.150527-6.jar这样的时间戳文件非常简单:

    root = 'path to your repository'
    
    new File(root).eachFileRecurse {
      if (it.name.matches(/.*\-\d{8}\.\d{6}\-\d+\.[\w\.]+$/)) {
        println 'Deleting ' + it.name
        it.delete()
      }
    }
    

    安装Groovy,将脚本保存到一个文件中,并在每周、开始、登录等任何适合您的时间安排执行

    或者,您甚至可以使用gmavenplus-plugin将执行连接到maven build中。注意,maven如何将存储库位置设置为属性settings.localRepository,然后通过配置绑定到变量repository

      <plugin>
        <groupId>org.codehaus.gmavenplus</groupId>
        <artifactId>gmavenplus-plugin</artifactId>
        <version>1.3</version>
        <executions>
          <execution>
            <phase>install</phase>
            <goals>
              <goal>execute</goal>
            </goals>
          </execution>
        </executions>
        <configuration>
          <properties>
            <property>
              <name>repository</name>
              <value>${settings.localRepository}</value>
            </property>
          </properties>
          <scripts>
            <script><![CDATA[
              new File(repository).eachFileRecurse {
                if (it.name.matches(/.*\-\d{8}\.\d{6}\-\d+\.[\w\.]+$/)) {
                  println 'Deleting snapshot ' + it.getAbsolutePath()
                  it.delete()
                }
              }
            ]]></script>
          </scripts>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.3.7</version>
            <scope>runtime</scope>
          </dependency>
        </dependencies>
      </plugin>  
    
  5. # 5 楼答案

    将以下参数添加到POM文件中

    POM

    <configuration>
    <outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>
    </configuration>
    

    https://maven.apache.org/plugins/maven-dependency-plugin/copy-mojo.html

    POM示例

    <plugins>
          <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
            <version>2.10</version>
            <executions>
              <execution>
                <id>copy</id>
                <phase>package</phase>
                <goals>
                  <goal>copy</goal>
                </goals>
                <configuration>
                  <artifactItems>
                    <artifactItem>
                      <groupId>junit</groupId>
                      <artifactId>junit</artifactId>
                      <version>3.8.1</version>
                      <type>jar</type>
                      <overWrite>false</overWrite>
                      <outputDirectory>${project.build.directory}/alternateLocation</outputDirectory>
                      <destFileName>optional-new-name.jar</destFileName>
                    </artifactItem>
                  </artifactItems>
                  **<outputAbsoluteArtifactFilename>true</outputAbsoluteArtifactFilename>**
                  <outputDirectory>${project.build.directory}/wars</outputDirectory>
                  <overWriteReleases>false</overWriteReleases>
                  <overWriteSnapshots>true</overWriteSnapshots>
                </configuration>
              </execution>
            </executions>
          </plugin>
        </plugins>
      </build>
    

    在Jenkins中配置:

    // copy artifact 
    copyMavenArtifact(artifact: "commons-collections:commons-collections:3.2.2:jar", outputAbsoluteArtifactFilename: "${pwd()}/target/my-folder/commons-collections.jar")
    
  6. # 6 楼答案

    该插件从本地存储库中删除项目的工件。仅保留大型本地快照的一个副本非常有用

    <plugin>         
        <groupId>org.codehaus.mojo</groupId>         
        <artifactId>build-helper-maven-plugin</artifactId>         
        <version>1.7</version>         
        <executions>           
            <execution>             
                <id>remove-old-artifacts</id>             
                <phase>package</phase>             
                <goals>               
                    <goal>remove-project-artifact</goal>             
                </goals>            
                <configuration>  
                    <removeAll>true</removeAll><!-- When true, remove all built artifacts including all versions. When false, remove all built artifacts of this project version -->             
                </configuration>          
            </execution>         
        </executions>       
    </plugin>