Статьи

Демонизация приложений на основе JVM

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

Вопросы обслуживания и эксплуатации, такие как безопасность развертывания, мониторинг, резервное копирование / восстановление и т. Д., Относятся к более широкой теме проектирования архитектуры развертывания. Эти проблемы носят сквозной характер и могут нуждаться в рассмотрении на разных уровнях — от процессов развертывания услуг до практических деталей управления системой.

На уровне детализации управления системой часто возникают следующие проблемы при использовании модели развертывания приложений, основанной исключительно на JVM (на Unix-подобных платформах):

  • Как безопасно закрыть сервер приложений или приложений? Часто используется поток прослушивателя TCP для прослушивания запросов на завершение работы. Если на одном хосте установлено несколько экземпляров одного и того же сервера приложений, иногда легко перепутать экземпляры и отключить неправильный. Также вам нужно будет предотвратить несанкционированный доступ к слушателю завершения работы.
  • создание сценариев инициализации, которые легко интегрируются с механизмами запуска и завершения работы системы (например, Sys-V init, systemd, Upstart и т. д.)
  • как автоматически перезапустить приложение, если оно умирает?
  • управление файлами журналов. Журналы приложений могут управляться (например, вращаться, сжиматься, удаляться) библиотекой журналов. Журналами сервера приложений или платформы также иногда можно управлять с помощью библиотеки журналов, но иногда может потребоваться интеграция с инструментами уровня ОС (например, logrotate).

Есть несколько решений этих проблем, которые обеспечивают более тесную интеграцию между операционной системой и сервером приложений / приложений. Одним из широко используемых и универсальных решений является Java Service Wrapper . Java Service Wrapper хорошо справляется с вышеуказанными проблемами и выпускается по закрытой лицензии. Также доступна опция лицензирования сообщества на основе GPL v2.

Apache commons daemon — это еще один вариант. Он имеет свои корни в Apache Tomcat и хорошо интегрируется с сервером приложений, но он гораздо более универсален, и, в дополнение к Java, демон commons может использоваться и с другими языками на основе JVM, такими как Scala. Как следует из названия, демон commons имеет лицензию Apache.

Демон Commons включает в себя следующие функции:

  • автоматически перезапустить JVM, если он умирает
  • включить безопасное завершение процесса JVM с использованием стандартных механизмов ОС (механизм выключения на основе Tomcat TCP подвержен ошибкам и небезопасен)
  • перенаправить STDERR / STDOUT и установить имя процесса JVM
  • разрешить интеграцию с механизмами сценариев инициализации ОС (записать pid процесса JVM)
  • отсоединить процесс JVM от родительского процесса и консоли
  • запустить JVM и приложение с ограниченными привилегиями ОС
  • позволяют координировать управление файлами журналов с помощью инструментов ОС, таких как logrotate (повторно открывать файлы журналов с сигналом SIGUSR1)

Развертывание демона commons

С точки зрения разработчика приложений, демон commons состоит из двух частей: двоичного файла jsvc, используемого для запуска приложений, и демона commons Java API. Во время запуска двоичный файл jsvc загружает приложение с помощью методов жизненного цикла, реализуемых приложением и определяемых демоном commons daemon Java API. Jsvc создает процесс управления для мониторинга и перезапуска приложения при аварийном завершении. Вот схема развертывания демона commons с вашим приложением:

  1. реализовать методы жизненного цикла API демона commons в классе начальной загрузки приложения (см. Использование jsvc напрямую ).
  2. скомпилируйте и установите jsvc. (Обратите внимание, что обычно не рекомендуется устанавливать набор инструментов компилятора на рабочие или QA-серверы).
  3. поместить API-интерфейс commons-daemon в путь к классам приложений
  4. выяснить аргументы командной строки для запуска вашего приложения через jsvc. Посмотрите bin / daemon.sh в дистрибутиве Tomcat для справки.
  5. создать правильный скрипт инициализации на основе предыдущего шага. Tomcat можно установить с помощью диспетчера пакетов во многих дистрибутивах Linux, и пакет обычно поставляется со скриптом инициализации, который можно использовать в качестве ссылки.

Практический опыт

В дистрибутив Tomcat входит «daemon.sh», универсальный сценарий оболочки-оболочки, который можно использовать в качестве основы для создания системного варианта сценария инициализации. Одна из проблем, с которой я столкнулся, заключалась в том, что значение по умолчанию для параметра конфигурации ожидания не могло быть переопределено инициатором сценария оболочки. В некоторых случаях инициализация генератора случайных чисел Tomcat может превышать максимальное время ожидания, что приводит к тому, что сценарий инициализации сообщает об ошибке, даже если сервер приложений в конечном итоге запустится. Кажется, это сейчас исправлено.

Другая проблема заключалась в том, что скрипт-обертка не позволяет передавать JVM-параметры с пробелами в них. Это может быть удобно, например, в сочетании с JVM «-XX: OnOutOfMemoryError» & co. параметры. Использование сценария-обертки не является обязательным, и его также можно легко изменить, но, поскольку он включает в себя некоторые полезные функции, я предпочел бы повторно использовать его вместо дублирования, поэтому я создал запрос функции и предложил крошечный патч для этого # 55104 .

При выяснении правильных аргументов командной строки для загрузки jsvc в ваше приложение, аргумент «-debug» может быть весьма полезен для устранения неполадок. Кроме того, по умолчанию jsvc меняет рабочий каталог на /, и в этом случае абсолютные пути обычно должны использоваться с другими параметрами. Опцию «-cwd» можно использовать для переопределения значения рабочего каталога по умолчанию.

Демонизирующая пристань

В дополнение к Tomcat, Jetty — еще один контейнер сервлетов, который я часто использую. Использование демона commons с Tomcat не представляет проблем, так как интеграция уже существует, поэтому я решил посмотреть, как все будет работать с сервером приложений, который не поддерживает демона commons «из коробки».

Чтобы реализовать необходимые изменения в Jetty, я клонировал репозиторий исходного кода Jetty, добавил методы жизненного цикла jsvc в класс начальной загрузки Jetty и собрал Jetty. После этого я начал экспериментировать с аргументами командной строки jsvc для начальной загрузки Jetty. Jetty поставляется с сценарием запуска jetty.sh, который имеет опцию «check» для вывода различной информации, связанной с установкой. Среди прочего он выводит аргументы командной строки, которые будут использоваться с JVM. Это обеспечило довольно хорошую отправную точку для командной строки jsvc.

Это командные строки, которыми я заканчивал:

1
2
3
export JH=$HOME/jetty-9.2.2-SNAPSHOT
export JAVA_HOME=`/usr/libexec/java_home -v 1.8`
jsvc -debug -pidfile $JH/jetty.pid -outfile $JH/std.out -errfile $JH/std.err -Djetty.logs=$JH/logs -Djetty.home=$JH -Djetty.base=$JH -Djava.io.tmpdir=/var/folders/g6/zmr61rsj11q5zjmgf96rhvy0sm047k/T/ -classpath $JH/commons-daemon-1.0.15.jar:$JH/start.jar org.eclipse.jetty.start.Main jetty.state=$JH/jetty.state jetty-logging.xml jetty-started.xml

Это может быть использовано в качестве отправной точки для правильного сценария инициализации производственного класса для запуска и выключения Jetty.

Я отправил свои изменения кода как проблему № 439672 в трекере проблем проекта Jetty и только что получил сообщение о том, что изменение было объединено с исходной кодовой базой, поэтому в будущем вы сможете иметь возможность демонизировать Jetty с демоном Apache commons dasmon jsvc. -коробка.