Лучший способ развернуть большой *.war на tomcat
Во время разработки мне часто приходится развертывать большой war-файл (~45 МБ) на удаленном тестовом сервере, обычно я копирую файл с помощью scp на сервер.
Папка WEB-INF/lib составляет большую часть файла war, который включает в себя все необходимые библиотеки (spring, apache-cxf, hibernate,...).
Сейчас я ищу быстрый и простой способ повторно развернуть только мои измененные файлы.
И как я могу определить, какие пакеты действительно нужны веб-приложению, потому что Spring и Apache-CXF поставляются с множеством библиотек, я уверен, что они мне не нужны.
5 ответов
При развертывании .war
Tomcat первым делом распаковывает этот файл в 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:
- распакуйте / разорвите обрезанную WAR, созданную сценарием ANT ниже
- скопируйте jar-файлы репозитория сервера в разобранный файл WEB-INF / lib
- почтовый индекс все в новую (большую) войну.
- развернуть как обычно.
Например:
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 помочь здесь. Это позволило бы вам разбить вашу проблему на модули, которые более независимы и могут быть заменены.
Просто любопытно:
- Сколько времени это займет сейчас?
- Используете ли вы непрерывную интеграцию для создания и развертывания?