Подтвердить что ты не робот

Рекомендации по развертыванию Java Webapps с минимальным временем простоя?

При развертывании большого Java webapp ( > 100 МБ .war) в настоящее время я использую следующий процесс развертывания:

  • Файл приложения .war расширяется локально на машине разработки.
  • Расширенное приложение - rsync: ed от машины разработки до живой среды.
  • Сервер приложений в живой среде перезапускается после rsync. Этот шаг не является абсолютно необходимым, но я обнаружил, что перезапуск сервера приложений при развертывании позволяет избежать "java.lang.OutOfMemoryError: PermGen space" из-за частых загрузок классов.

Хорошие вещи об этом подходе:

  • rsync минимизирует количество данных, отправленных с машины разработки в живую среду. Загрузка всего файла .war занимает более десяти минут, тогда как rsync занимает пару секунд.

Плохие вещи об этом подходе:

  • Во время запуска rsync контекст приложения перезапускается с момента обновления файлов. В идеале перезапуск должен происходить после завершения rsync, а не при его запуске.
  • Перезапуск сервера приложений вызывает примерно две минуты простоя.

Я хотел бы найти процесс развертывания со следующими свойствами:

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

Вопрос:

  • С учетом заявленных требований, каков оптимальный процесс развертывания?
4b9b3361

Ответ 1

Было отмечено, что rsync плохо работает при нажатии на изменения в файле WAR. Причиной этого является то, что файлы WAR являются по существу ZIP файлами и по умолчанию создаются сжатыми файлами-членами. Небольшие изменения в файлах-членах (до сжатия) приводят к крупномасштабным различиям в файле ZIP, рендеринг алгоритма дельта-передачи rsync неэффективен.

Одним из возможных решений является использование jar -0 ... для создания исходного файла WAR. Опция -0 сообщает команде jar не сжимать файлы-члены при создании WAR файла. Затем, когда rsync сравнивает старые и новые версии WAR файла, алгоритм дельта-передачи должен иметь возможность создавать небольшие различия. Затем организуйте, чтобы rsync отправил diff (или исходные файлы) в сжатой форме; например используйте rsync -z ... или сжатый поток данных/транспорт под ним.

EDIT: в зависимости от того, как структурирован файл WAR, также может потребоваться использовать jar -0 ... для создания JAR файлов компонента. Это применимо к файлам JAR, которые часто могут быть изменены (или просто перестроены), а не к стабильным сторонним JAR файлам.

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

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


Другой подход полностью состоял бы в том, чтобы посмотреть ваш файл WAR, чтобы узнать, можете ли вы определить библиотеки JAR, которые могут (почти) никогда не меняться. Извлеките эти JAR из WAR файла и разложите их отдельно в каталог common/lib сервера Tomcat; например используя rsync.

Ответ 2

Обновление:

Поскольку этот ответ был впервые написан, появился лучший способ развернуть военные файлы на tomcat с нулевым временем простоя. В последних версиях tomcat вы можете включать номера версий в свои военные имена. Так, например, вы можете развернуть файлы ROOT##001.war и ROOT##002.war в один и тот же контекст одновременно. Все после ## интерпретируется как номер версии tomcat, а не частью пути к контексту. Tomcat будет поддерживать все версии вашего приложения и обслуживать новые запросы и сеансы до последней версии, которая полностью завершается, изящно завершая старые запросы и сеансы в версии, с которой они начали работать. Указание номеров версий также можно выполнить с помощью диспетчера tomcat и даже для каталитических задач ant. Подробнее здесь.

Исходный ответ:

Rsync имеет тенденцию быть неэффективным для сжатых файлов, так как алгоритм дельта-передачи ищет изменения в файлах и небольшое изменение несжатого файла, может радикально изменить результирующую сжатую версию. По этой причине было бы целесообразно rsync несвязанный файл войны, а не сжатую версию, если сетевая полоса окажется узким местом.

Что не так с использованием приложения Tomcat manager для развертывания? Если вы не хотите загружать весь файл войны непосредственно в приложение менеджера Tomcat из удаленного местоположения, вы можете rsync его (несжатый по причинам, указанным выше) в месте расположения в окне производства, переупаковать его на войну и затем передайте его менеджеру локально. Существует хорошая задача ant, которая поставляется с Tomcat, позволяющая развертывать script с помощью приложения менеджера Tomcat.

В вашем подходе есть еще один недостаток, о котором вы не упоминали: хотя ваше приложение частично развернуто (во время операции rsync), ваше приложение может находиться в несогласованном состоянии, когда измененные интерфейсы могут быть не синхронизированы, новые/обновленные зависимости могут быть недоступны и т.д. Кроме того, в зависимости от того, сколько времени займет ваше задание rsync, ваше приложение может перезапустить несколько раз. Знаете ли вы, что вы можете и должны отключить поведение прослушивания для измененных файлов и перезапуска в Tomcat? Это фактически не рекомендуется для производственных систем. Вы всегда можете выполнить ручной или ant перезапуск скриптов с помощью приложения Tomcat manager.

Конечно, ваше приложение будет недоступно пользователям во время перезагрузки. Но если вы так обеспокоены наличием, у вас наверняка есть избыточные веб-серверы за балансировщиком нагрузки. При развертывании обновленного военного файла вы можете временно оставить балансировщик нагрузки отправлять все запросы на другие веб-серверы до завершения развертывания. Прополощите и повторите для других веб-серверов.

Ответ 3

В любой среде, где время простоя является соображением, вы, безусловно, запускаете своего рода кластер серверов для повышения надежности за счет избыточности. Я бы взял хозяина из кластера, обновил его, а затем выбросил обратно в кластер. Если у вас есть обновление, которое не может работать в смешанной среде (например, несовместимое изменение схемы, требуемое для db), вам нужно будет удалить весь сайт, по крайней мере, на мгновение. Хитрость заключается в том, чтобы вызвать процессы замещения перед удалением оригиналов.

Используя tomcat в качестве примера, вы можете использовать CATALINA_BASE для определения каталога, в котором будут найдены все рабочие каталоги tomcat, отдельно от исполняемого кода. Каждый раз, когда я развертываю программное обеспечение, я развертываю его в новый базовый каталог, чтобы иметь новый код на диске рядом со старым кодом. Затем я могу запустить еще один экземпляр tomcat, который указывает на новый базовый каталог, запустит все его работу и затем заменит старый процесс (номер порта) на новый в балансировщике нагрузки.

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

Это все компромисс между ИТ-инфраструктурой, сложностью процесса выпуска и усилиями разработчиков. Если ваш кластер достаточно велик и ваше желание достаточно сильное, достаточно легко создать систему, которая может быть заменена без простоя вообще для большинства обновлений. Большие изменения схемы часто приводят к фактическому простою, поскольку обновленное программное обеспечение обычно не может использовать старую схему, и вам, вероятно, не удастся избежать копирования данных на новый экземпляр db, выполнить обновление схемы и затем переключить серверы на новый db, поскольку вы будете пропускать любые данные, записанные в старые после того, как новый db был клонирован из него. Конечно, если у вас есть ресурсы, вы можете поручить разработчикам изменить новое приложение, чтобы использовать новые имена таблиц для всех обновляемых таблиц, и вы можете поместить триггеры на место live db, которые будут правильно обновлять новые таблицы с данными как он записывается в старые таблицы по предыдущей версии (или, возможно, использует представления для эмуляции одной схемы из другой). Поднимите новые серверы приложений и замените их в кластер. Есть тонна игр, которые вы можете играть, чтобы минимизировать время простоя, если у вас есть ресурсы разработки для их создания.

Возможно, самый полезный механизм сокращения времени простоя при обновлении программного обеспечения - это убедиться, что ваше приложение может работать в режиме только для чтения. Это предоставит пользователям необходимую функциональность, но предоставит вам возможность делать общесистемные изменения, требующие изменений в базе данных. Поместите приложение в режим только для чтения, затем клонируйте данные, обновите схему, поднимите новые серверы приложений против нового db, затем переключите балансировщик нагрузки, чтобы использовать новые серверы приложений. Единственное время простоя - это время, необходимое для перехода в режим только для чтения и время, необходимое для изменения конфигурации вашего балансировщика нагрузки (большинство из которых может обрабатывать его без какого-либо простоя).

Ответ 4

Мой совет - использовать rsync с взорванными версиями, но развернуть военный файл.

  • Создайте временную папку в живой среде, где у вас будет взорванная версия webapp.
  • Rsync взорванные версии.
  • После успешного создания rsync создайте военный файл во временной папке на машине с живой средой.
  • Замените старую войну в каталоге развертывания сервера новым с временной папки.

Замена старой войны на новую рекомендуется в контейнере JBoss (который основан на Tomcat) beacause it'a атомная и быстрая работа, и он уверен, что при запуске приложения развертывания все приложение будет находиться в развернутом состоянии.

Ответ 5

Не можете ли вы сделать локальную копию текущего веб-приложения на веб-сервере, rsync в этот каталог, а затем, возможно, даже используя символические ссылки, в одном "ходу", укажите Tomcat на новое развертывание без большого времени простоя?

Ответ 6

Горячее развертывание Java EAR для минимизации или устранения простоя приложения на сервере или Как "горячее" развертывание военная зависимость в Jboss с использованием Jboss Tools Плагин Eclipse может иметь некоторые варианты для вас.

Интересно также развертывание в кластере без простоя.

JavaRebel имеет развертывание горячего кода.

Ответ 7

Ваш подход к rsync извлеченной войне довольно хорош, а также перезапуск, так как я считаю, что на рабочем сервере не должно быть включено горячее развертывание. Итак, единственным недостатком является время простоя, когда вам нужно перезагрузить сервер, не так ли?

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

Запустить два сервера приложений. Запустите второй сервер приложений (который прослушивает другие порты TCP) и разверните там свое приложение. После развертывания обновите конфигурацию Apache httpd (mod_jk или mod_proxy), чтобы указать на второй сервер приложений. Изящно перезапустив процесс Apache httpd. Таким образом, у вас не будет простоев, и новые пользователи и запросы автоматически перенаправляются на новый сервер приложений.

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

Ответ 8

Это зависит от архитектуры вашего приложения.

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

Ответ 9

Если статические файлы являются большой частью вашей большой WAR (100Mo довольно большой), то размещение их вне WAR и развертывание их на веб-сервере (например, Apache) перед вашим сервером приложений может ускорить работу. Кроме того, Apache обычно выполняет лучшую работу по обслуживанию статических файлов, чем делает механизм сервлетов (даже если большинство из них достигли значительного прогресса в этой области).

Итак, вместо того, чтобы производить большую жирную WAR, поставьте ее на диету и произведите:

  • большой толстый ZIP со статическими файлами для Apache
  • менее жирная WAR для сервлет-двигателя.

По желанию, пойдите дальше в процессе создания WAR тоньше: если возможно, разверните Grails и другие JAR, которые не часто меняются (что, скорее всего, и в большинстве случаев) на уровне сервера приложений.

Если вам удастся создать более легкую WAR, я бы не стал беспокоиться о rsyncing-каталогах, а не в архивах.

Сильные стороны этого подхода:

  • Статические файлы могут быть горячими "развернуты" на Apache (например, используйте символическую ссылку, указывающую на текущий каталог, распакуйте новые файлы, обновите символическую ссылку и voilà).
  • WAR будет тоньше, и для его развертывания потребуется меньше времени.

Слабость этого подхода:

  • Существует еще один сервер (веб-сервер), чтобы добавить (немного) больше сложности.
  • Вам нужно будет изменить скрипты сборки (а не IMO).
  • Вам нужно будет изменить логику rsync.

Ответ 10

Я не уверен, отвечает ли это на ваш вопрос, но я просто расскажу о процессе развертывания, который я использую или встречаюсь в нескольких проектах, которые я сделал.

Если вы знакомы с вами, я никогда не вспоминаю о том, чтобы начать полную переделку или обновление войны. В большинстве случаев мои обновления ограничены несколькими файлами jsp, возможно, библиотекой, некоторыми файлами классов. Я могу управлять и определять, какие из них являются затронутыми артефактами, и обычно мы упаковывали эти обновления в zip файл вместе с обновлением script. Я запустил обновление script. script выполняет следующие действия:

  • Резервное копирование файлов, которые будут перезаписаны, возможно, в папку с сегодняшней датой и временем.
  • Распакуйте файлы
  • Остановить сервер приложений
  • Переместите файлы поверх
  • Запустить сервер приложений

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

Еще одна вещь, которая мне интересна, - зачем нужна rsync? Вы должны знать, какие требуемые изменения, определяя их в своей промежуточной среде/среде разработки, не выполняя дельта-проверки в режиме реального времени. В большинстве случаев вам придется настраивать rsync, чтобы игнорировать файлы в любом случае, например, определенные файлы свойств, определяющие ресурсы, используемые производственным сервером, такие как подключение к базе данных, smtp-сервер и т.д.

Я надеюсь, что это будет полезно.

Ответ 11

В чем ваш комплект PermSpace? Я ожидал бы, что это будет расти, но должно пойти вниз после сбора старых классов? (или класс ClassLoader все еще сидит?)

Размышляя об аудите, вы можете rsync в отдельную директорию с именем или именем. Если контейнер поддерживает символические ссылки, вы можете SIGSTOP в корневом процессе, переключите корень контекстной файловой системы через символическую ссылку, а затем SIGCONT?

Ответ 12

Что касается раннего контекста перезагрузки. Все контейнеры имеют параметры конфигурации, чтобы отключить автоматическое повторное развертывание в файле класса или изменении статического ресурса. Вероятно, вы не можете отключить автоматическое повторное развертывание в изменениях web.xml, чтобы этот файл был последним для обновления. Поэтому, если вы отключите автоматическое повторное развертывание и обновление web.xml в качестве последнего, вы увидите перезапуск контекста после всего обновления.

Ответ 13

Мы загружаем новую версию webapp в отдельный каталог, затем либо переходим на ее замену с запущенным, либо используем символические ссылки. Например, у нас есть символическая ссылка в каталоге tomapat webapps с именем "myapp", которая указывает на текущий webapp с именем "myapp-1.23". Мы загружаем новый webapp в "myapp-1.24". Когда все будет готово, остановите сервер, удалите символическую ссылку и создайте новую, указывающую на новую версию, а затем запустите сервер снова.

Мы отключили автоматическую перезагрузку на рабочих серверах для повышения производительности, но даже при том, что файлы внутри webapp изменяются неатомно, это может вызвать проблемы, поскольку статические файлы или даже страницы JSP могут меняться способами, которые вызывают нерабочие ссылки или хуже.

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

Основным недостатком вашей ситуации является то, что загрузка займет больше времени, так как ваш метод позволяет rsync передавать только измененные или добавленные файлы. Вы можете сначала скопировать старую папку webapp в новую, а затем rsync, если это имеет существенное значение, и если это действительно проблема.

Ответ 14

Tomcat 7 имеет приятную функцию " параллельное развертывание", которая предназначена для этого варианта использования.

Суть в том, что вы расширяете .war в каталог, либо непосредственно под webapps/или symlinked. Последовательные версии приложения находятся в каталогах с именем app##version, например myapp##001 и myapp##002. Tomcat будет обрабатывать существующие сеансы, идущие на старую версию, и новые сессии, идущие в новую версию.

Уловка заключается в том, что вы должны быть очень осторожны с утечками PermGen. Это особенно верно для Grails, который использует много PermGen. VisualVM - ваш друг.

Ответ 15

Просто используйте 2 или более сервера tomcat с прокси-сервером. Этот прокси-сервер может быть apache/nignix/haproxy.

Теперь на каждом прокси-сервере есть "in" и "out" url с настройками портов.

Сначала скопируйте свою войну в tomcat, не останавливая службу. После развертывания войны он автоматически открывается двигателем tomcat.

Перекрестная проверка примечаний unpackWARs = "true" и autoDeploy = "true" в node "Host" внутри server.xml

Кажется, это нравится

  <Host name="localhost"  appBase="webapps"
        unpackWARs="true" autoDeploy="true"
        xmlValidation="false" xmlNamespaceAware="false">

Теперь просмотрите журналы tomcat. Если нет ошибки, это означает, что она успешно завершена.

Теперь нажмите все API для тестирования

Теперь перейдите на ваш прокси-сервер.

Просто измените отображение фонового URL с новым военным именем. Поскольку регистрация на прокси-серверах, таких как apache/nignix/haProxy, заняла очень мало времени, вы будете чувствовать минимальное время простоя

Refer - https://developers.google.com/speed/pagespeed/module/domains для сопоставления URL-адресов

Ответ 16

Вы используете Resin, Resin имеет встроенную поддержку для управления версиями веб-приложений.

http://www.caucho.com/resin-4.0/admin/deploy.xtp#VersioningandGracefulUpgrades

Обновление: этот сторожевой процесс также может помочь в проблемах с перминпространством.

Ответ 17

Не "лучшая практика", а то, о чем я только подумал.

Как насчет развертывания webapp через DVCS, например git?

Таким образом вы можете позволить git определить, какие файлы нужно передать на сервер. У вас также есть хороший способ отступить от него, если окажется, что он разорен, просто сделайте возврат!

Ответ 18

Я написал bash script, который принимает несколько параметров и rsyncs файл между серверами. Ускоряет передачу rsync для больших архивов:

https://gist.github.com/3985742