Лучший способ развернуть большой *.war на tomcat

Во время разработки мне часто приходится развертывать большой war-файл (~45 МБ) на удаленном тестовом сервере, обычно я копирую файл с помощью scp на сервер.

Папка WEB-INF/lib составляет большую часть файла war, который включает в себя все необходимые библиотеки (spring, apache-cxf, hibernate,...).

Сейчас я ищу быстрый и простой способ повторно развернуть только мои измененные файлы.

И как я могу определить, какие пакеты действительно нужны веб-приложению, потому что Spring и Apache-CXF поставляются с множеством библиотек, я уверен, что они мне не нужны.

5 ответов

Решение

При развертывании .warTomcat первым делом распаковывает этот файл в webapps каталог, в подкаталоге с тем же именем, что и ваш .war,

Во время разработки у вас, очевидно, есть доступ к вашему .class файлы, .jar файлы, файлы конфигурации и все остальное, что в конечном итоге входит в ваш .war, Вы можете легко создать небольшое подмножество файлов, затронутых вашими изменениями. Выясните это, а затем используйте скрипт или ant задача или что-то, чтобы скопировать только эту небольшую горстку файлов прямо в webapps/yourapp каталог на сервере.

Чтобы изменения вступили в силу, вам нужно перезапустить приложение. Если Tomcat находится в режиме разработки, одним из простых способов принудительной перезагрузки (и, конечно, перезагрузки) является обновление WEB-INF/web.xml, Итак, ваш процесс развертывания touch этот файл или иным образом обновить его таким образом, чтобы дать ему новую метку времени, scp это слишком (желательно как последний из файлов, которые вы обновляете), и вы должны иметь быструю и простую перезагрузку.

Что я делаю, так это исключаю файлы WEB-INF/lib/*. Jar из WAR и собираю их на стороне сервера. В моем случае это сокращает 60 МБ WAR до 250 КБ, что обеспечивает действительно быстрое развертывание.

<exclude name="**/lib/*.jar"/> команда - это то, что исключает банку (см. последний фрагмент кода для сборки ANT)

Со стороны сервера довольно просто собрать полностью заполненную WAR из урезанной WAR:

  1. распакуйте / разорвите обрезанную WAR, созданную сценарием ANT ниже
  2. скопируйте jar-файлы репозитория сервера в разобранный файл WEB-INF / lib
  3. почтовый индекс все в новую (большую) войну.
  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>           

Улучшение ответа Рори Штумпфа, вот задача 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 (весом менее 1 МБ) и ZIP-архив libs.

разверните тонкую войну на сервере (и восстановите там библиотеки) и разверните zip-архив libs при каждом изменении версий / добавления библиотек.

Я использую rsync скопировать мой .war от моей местной машины до производства. Это обычно обеспечивает большую скорость, около 8-10 раз.

Другой вариант заключается в использовании git хранить .war файлы. Когда ты git push новый .war, только различия передаются. Также большая скорость. Некоторые люди говорят, что git не предназначен для хранения больших файлов, он работает медленно и работает не очень хорошо. На самом деле, репо сильно вырастет, но в некоторых случаях это может быть хорошим вариантом.

Некоторые цифры: мой .war составляет около 50 МБ, и когда я развертываю новую версию, он копирует всего около 4 МБ вместо загрузки новой войны. Оба с git а также rsync,

ОБНОВЛЕНИЕ: проблема, с которой я столкнулся, состоит в том, что репозиторий git не может быть клонирован после того, как у него есть несколько .war версий, потому что для создания всех дельт и передачи их клиенту потребуется вечность.

Я изменил стратегию, загрузив .war файлы в Dropbox. Dropbox также использует вид rsync и только копирует дельты. С сервера я вижу .war и повторно выполните приложение. Надеюсь это поможет.

Я не думаю, что есть более быстрый способ повторно развернуть только изменения в файле WAR.

Если вы развернете в разобранном виде, вы сможете увидеть, какие временные метки файла изменились, и действовать соответствующим образом, но для этого вам придется написать код.

Я не знаю, может ли OSGi помочь здесь. Это позволило бы вам разбить вашу проблему на модули, которые более независимы и могут быть заменены.

Просто любопытно:

  1. Сколько времени это займет сейчас?
  2. Используете ли вы непрерывную интеграцию для создания и развертывания?
Другие вопросы по тегам