【问题标题】:Best way to deploy large *.war to tomcat将大型 *.war 部署到 tomcat 的最佳方式
【发布时间】:2011-03-12 05:36:39
【问题描述】:

在开发过程中,我经常需要将大型战争文件 (~45 MB) 部署到远程测试服务器,通常我使用 scp 将文件复制到服务器。

WEB-INF/lib 文件夹构成了 war 文件的最大部分,其中包括所有必需的库(spring、apache-cxf、hibernate...)。

现在我正在寻找一种快速简便的方法来仅重新部署我更改的文件。

以及如何确定 webapp 真正需要哪些包,因为 spring 和 apache-cxf 带有很多库,我确定我不需要所有这些。

【问题讨论】:

    标签: deployment tomcat war


    【解决方案1】:

    当您部署.war 时,Tomcat 所做的第一件事就是将该文件解压缩到其webapps 目录中,该目录与您的.war 同名。

    在开发过程中,您显然可以访问您的.class 文件、.jar 文件、配置文件以及最终进入您的.war 的任何其他内容。您可以轻松地建立一小部分受您的更改影响的文件。弄清楚这一点,然后使用脚本或ant 任务或其他任何方式将少量文件直接复制到服务器上的webapps/yourapp 目录中。

    要让您的更改生效,您需要重新启动您的应用程序。如果 Tomcat 处于开发模式,一种强制重新加载(当然是重新启动)的简单方法是更新 WEB-INF/web.xml。因此,让您的部署过程touch 该文件或以其他方式更新它,从而为其提供一个新的时间戳,scp 也结束(最好作为您更新的最后一个文件),您应该有一个快速而简单的重新加载。

    【讨论】:

      【解决方案2】:

      我所做的是从 WAR 中排除 WEB-INF/lib/*.jar 文件并在服务器端重新组装。就我而言,这会将 60MB WAR 缩减至 250k,从而实现真正快速的部署。

      <exclude name="**/lib/*.jar"/> 命令是不包括 jar 的(请参阅最后的代码 sn-p 用于 ANT 构建)

      在服务器端,很容易从修剪后的 WAR 组装一个完全填充的 WAR:

      1. 解压/分解由下面的 ANT 脚本创建的修剪后的 WAR
      2. 将服务器存储库 jar 文件复制到展开的 WEB-INF/lib 中
      3. zip 已全部进入一个新的(大型)WAR。
      4. 照常部署。

      例如:

      unzip ../myapp.trimmed.war
      mkdir WEB-INF/lib
      cp ../war_lib_repository/* WEB-INF/lib
      zip -r ../myapp.war .
      

      也许不是最优雅的解决方案,但它节省了频繁部署大型 WAR 的时间。我希望能够用 Maven 做到这一点,所以如果有人有建议,请告诉我。

      ANT build.xml:

      <property file="build.properties"/>
      <property name="war.name" value="myapp.trimmedwar"/>
      <property name="deploy.path" value="deploy"/>   
      <property name="src.dir" value="src"/>
      <property name="config.dir" value="config"/>
      <property name="web.dir" value="WebContent"/>
      <property name="build.dir" value="${web.dir}/WEB-INF/classes"/>
      <property name="name" value="${war.name}"/>
      
      <path id="master-classpath">
          <fileset dir="${web.dir}/WEB-INF/lib">
              <include name="*.jar"/>         
          </fileset>
          <!-- other classes to include -->
          <fileset dir="${birt.runtime}/ReportEngine/lib">
              <include name="*.jar"/>
          </fileset>
          <pathelement path="${build.dir}"/>
      </path> 
      
      <target name="build" description="Compile main source tree java files">
          <mkdir dir="${build.dir}"/>
          <javac destdir="${build.dir}" debug="true" deprecation="false" optimize="false" failonerror="true">
              <src path="${src.dir}"/>
              <classpath refid="master-classpath"/>
          </javac>
      </target>
      
      <target name="createwar" depends="build" description="Create a trimmed WAR file (/lib/*.jar) excluded for size">
          <!-- copy the hibernate config file -->
          <copy todir="${web.dir}/WEB-INF/classes">
              <!-- copy hibernate configs -->
              <fileset dir="${src.dir}/" includes="**/*.cfg.xml" />
          </copy>     
          <copy todir="${web.dir}/WEB-INF/classes">
              <fileset dir="${src.dir}/" includes="**/*.properties" />
          </copy>             
          <!-- copy hibernate classes -->
          <copy todir="${web.dir}/WEB-INF/classes" >
              <fileset dir="${src.dir}/" includes="**/*.hbm.xml" />
          </copy>
          <war destfile="${name}.war" webxml="${web.dir}/WEB-INF/web.xml">
              <fileset dir="${web.dir}">
                  <include name="**/*.*"/>
                  <!-- exlude the jdbc connector because it's on the server's /lib/common -->
                  <exclude name="**/mysql-connector*.jar"/>
                  <!-- exclude these jars because they're already on the server (will be wrapped into the trimmed war at the server) -->
                  <exclude name="**/lib/*.jar"/>
              </fileset>
          </war>
          <copy todir="${deploy.path}" preservelastmodified="true">
              <fileset dir=".">
                  <include name="*.war"/>
              </fileset>
          </copy>
      </target>           
      

      【讨论】:

        【解决方案3】:

        我使用rsync 将我的.war 从本地机器复制到生产环境。它通常提供很大的加速,大约 8-10 倍。

        另一种选择是使用git 来存储.war 文件。当您 git push 一个新的 .war 时,只会传输差异。也有很大的提速。有人说 git 不是为存储大文件而设计的,它会变得很慢并且不能很好地工作。事实上,是的,repo 会增长很多,但在某些情况下它可能是一个不错的选择。

        一些数字:我的.war 大约是 50MB,当我部署一个新版本时,它只复制大约 4MB,而不是上传一个完整的新战争。 gitrsync

        更新:我遇到的问题是 git repo 在它有多个 .war 版本后无法克隆,因为创建所有增量并将它们传输到客户端需要很长时间。

        我通过将.war 文件上传到保管箱来更改策略。 Dropbox 也使用rsync 的类型,并且只复制增量。从服务器我得到.war 并重新部署应用程序。希望这会有所帮助。

        【讨论】:

        • rsync 非常快!我的应用程序只需几秒钟而不是 5-7 分钟。调试速度与本地机器上的一样快。非常感谢!
        【解决方案4】:

        改进 Rori Stumpf 的答案,这里是“细化”的 Gradle 任务

        war {
            archiveName "v1.war"
        }
        
        task createThinWar(type: Copy) {
            dependsOn 'war'
        
            def tmpFolder = "${buildDir}/tmp/thin"
            def outputDir = "${buildDir}/libs"
        
            // Extract the war (zip) contents
            from zipTree("${outputDir}/v1.war")
            into "${tmpFolder}/v1"
        
            doLast {
                // Extracting the war third party libraries to a separate dir
                ant.move(file: "${tmpFolder}/v1/WEB-INF/lib", tofile: "${tmpFolder}/v1-libs")
        
                // Zip the third party libraries dir
                ant.zip(destfile: "${outputDir}/v1-libs.zip") {
                    fileset(dir: "${tmpFolder}/v1-libs")
                }
        
                // Finally zip the thinned war back
                ant.zip(destfile: "${outputDir}/v1-thin.war") {
                    fileset(dir: "${tmpFolder}/v1")
                }
            }
        }
        

        这将生成 v1-thin.war(重量小于 1mb)和一个 libs zip。

        将瘦战争部署到服务器(并在那里重建库),并在您修改版本/添加库时部署库 zip。

        【讨论】:

          【解决方案5】:

          我认为没有更快的方法来仅重新部署对 WAR 文件的更改。

          如果您以爆炸方式部署,您可以看到哪些文件时间戳发生了变化并采取相应措施,但您必须编写代码才能做到这一点。

          我不知道 OSGi 是否可以在这里提供帮助。这将允许您将问题划分为更独立和可交换的模块。

          只是好奇:

          1. 现在需要多长时间?
          2. 您是否使用持续集成来构建和部署?

          【讨论】:

          • 最大的问题是上传到远程服务器的时间,它自己运行的部署又快又干净。我只能在远程服务器上测试漏洞 webapp,因为构建 webapp 的子系统庞大而复杂。
          猜你喜欢
          • 1970-01-01
          • 2020-06-17
          • 2018-05-18
          • 1970-01-01
          • 1970-01-01
          • 2015-03-10
          • 2018-12-05
          • 2018-03-13
          • 2017-07-07
          相关资源
          最近更新 更多