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

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

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

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

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

Ответ 1

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

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

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

Ответ 2

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

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

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

  • unzip/explode обрезанная WAR, созданная ANT script ниже
  • копировать файлы jar файлов репозитория сервера в вложенные WEB-INF/lib
  • zip все в новую (большую) WAR.
  • развертывать как обычно.

Например:

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 on the server /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 не предназначен для хранения больших файлов, он замедляется и не работает очень хорошо. На самом деле да, репо будет расти много, но в некоторых случаях это может быть хорошим вариантом.

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

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

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

Ответ 4

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

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

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

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

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