Лучший способ развернуть большой * .war на tomcat - PullRequest
11 голосов
/ 06 июля 2010

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

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

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

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

Ответы [ 5 ]

6 голосов
/ 06 июля 2010

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

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

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

2 голосов
/ 03 апреля 2012

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

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

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

  1. распаковать / разложить урезанную WAR, созданную сценарием ANT ниже
  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>           

1 голос
/ 13 марта 2014

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

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

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

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

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

0 голосов
/ 18 апреля 2018

Улучшение ответа Рори Штумпфа, вот задача 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 при каждом изменении версий / добавлении библиотек.

0 голосов
/ 06 июля 2010

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

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

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

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

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