Привет, Хабр!

Выступление Себастьяна Дашнера на java meetup в московском офисе IBM (нашел запись похожего выступления) подтолкнуло меня начать свое знакомство с легковесными серверами приложений, в частности, с OpenLiberty. И тогда я задумался:

  1. Какие преимущества дают легковесные сервера приложений?
  2. Как меняется специфика работы при их использовании?
  3. Зачем упаковывать сервер приложений в контейнер?

Отвечая на эти вопросы, я заметил, что информации по этой теме в открытом доступе мало, потому решил собрать и систематизировать её здесь.

Результаты выкладываю под катом.

Какие преимущества дают легковесные сервера приложений?


Раньше корпоративные серверы приложений Java EE (такие как JBoss AS, Oracle WebLogic, IBM WebSphere AS) считались тяжеловесной и громоздкой конструкцией, особенно, если мы говорим о времени запуска и развертывания. Но облачные технологии захватывают все большую часть индустрии и требования к серверам приложений меняются.

И вот, на смену полнофункциональным, корпоративным серверам приложений, приходят быстрые, модульные, небольшие сервера приложений, сфокусированные на выполнение определенной задачи: Thorntail, Payara Micro – младшие братья WildFly и Payara; Meecrowave – легковесный JAX-RS+CDI+JSON сервер, KumuluzEE – сервер, позволяющий расширять Java EE с помощью Node.js, Go и прочие.

В этот список входит и OpenLiberty — open source сервер приложений (распространяется по EPL-1.0) поддерживающий самые последние стандарты Java EE/Microprofile, на базе которого работает WebSphere Liberty.

Вкратце об особенностях EPL-1.0 (Eclipse Public License Version 1.0)
EPL 1.0 базируется на CPL и не совместима с GPL, разрешает соблюдать другие лицензии и патенты, которые используются в работе, и предоставляет право лицензировать продукт под любой другой лицензией, копия лицензии должна быть включена во все копии программы.

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

Связывание программного проекта с кодом, защищённым лицензией EPL (например, использование этого кода в качестве библиотеки), в общем случае, не делает этот проект производной работой и не накладывает соответствующих обязательств.

Участник, который включает Программу в коммерческое предложение, должен сделать это так, чтобы избежать потенциальной ответственности за других Участников. (явно отказаться от любых гарантий и ответственности от лица всех авторов)

Например: Участник может включить Программу в коммерческое предложение, продукт X. Тогда этот участник является Коммерческим участником. Если этот Коммерческий участник затем делает утверждения о скорости работы или предлагает гарантии по продукту X, эти утверждения и предложения являются персональной ответственностью Коммерческого участника. В рамках данного раздела Коммерческий участник должен защищать других Участников от претензий, относящихся к производительности и гарантиям, и если суд потребует любого другого Участника оплатить какой-либо результирующий ущерб, Коммерческий участник должен оплатить эти убытки.

Давайте посмотрим, какие преимущества мы можем получить, развернув приложение в контейнере с OpenLiberty. (У вас должна быть установлена любая версия java, дальнейшие действия необходимо выполнять, находясь в директории wlp)

Скорость:


Скорость — важнейший показатель для облачного приложения, ведь для того, чтобы облачное приложение быстро масштабировалось, управлялось и справлялось с растущей нагрузкой, оно должно запускаться за считанные секунды. Легковесный сервер приложений способен сделать это. Чтобы проверить — скачаем сервер OpenLiberty и выполним bin/server run (полный список команд):

$ bin/server run
 
Запуск defaultServer (Open Liberty 19.0.0.6/wlp-1.0.29.cl190620190617-1530) в Java HotSpot(TM) 64-Bit Server VM версии 1.8.0_212-b10 (ru_US)
[AUDIT   ] CWWKE0001I: Сервер defaultServer запущен.
[AUDIT   ] CWWKZ0058I: Выполняется мониторинг dropins для приложений.
[AUDIT   ] CWWKF0012I: На сервере установлены следующие комплекты: [el-3.0, jsp-2.3, servlet-3.1].
[AUDIT   ] CWWKF0011I: Сервер defaultServer готов к работе для разумной планеты. Сервер defaultServer запущен за 1,709 сек.

Модульность и гибкость


Большинству приложений не нужна Java EE целиком, а требуется выделенный набор стандартов, чаще всего используемый в enterprise-приложениях. Благодаря OSGI, мы можем выбрать нужный нам набор стандартов Java EE и/или MicroProfile, игнорируя все остальное.

Например, объявим JAX-RS из Java EE и mpHealth из Microprofile, добавив пару строк в featureManager блок usr/servers/serverName/server.xml

<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">
 
   <!-- Enable features -->
   <featureManager>
       <feature>jsp-2.3</feature>
       <feature>mpHealth-1.0</feature>
       <feature>jaxrs-2.1</feature>
   </featureManager>
 
   <!-- To access this server from a remote client add a host attribute to the following element, e.g. host="*" -->
   <httpEndpoint id="defaultHttpEndpoint"
                 httpPort="9080"
                 httpsPort="9443" />
 
   <!-- Automatically expand WAR files and EAR files -->
   <applicationManager autoExpand="true"/>
</server>

Динамическое обновление


В процессе разработки программный код и конфигурация постоянно изменяются.
Сервер приложений настроен для мониторинга изменений, и при необходимости переконфигурирует и развернет приложение на лету. Вот например, реакция на последние изменения:

[AUDIT   ] CWWKG0016I: Начато обновление конфигурации сервера.
[AUDIT   ] CWWKG0017I: Конфигурация сервера успешно обновлена за 0,475 сек.
[AUDIT   ] CWWKF0012I: На сервере установлены следующие комплекты: [cdi-2.0, jaxrs-2.1, jaxrsClient-2.1, jndi-1.0, json-1.0, jsonp-1.1, mpHealth-1.0, servlet-4.0].
[AUDIT   ] CWWKF0013I: С сервера удалены следующие комплекты: [servlet-3.1].
[AUDIT   ] CWWKF0008I: Обновление комплектов выполнено за 0,476 сек. 

Размер и сборка образа


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

В dockerhub есть готовые образы, содержащие предварительно настроенный сервер OpenLiberty. Воспользуемся одним из них и создадим Dockerfile:

FROM open-liberty
 
COPY usr/servers/defaultServer /opt/ol/wlp/usr/servers/defaultServer
 
ENTRYPOINT ["/opt/ol/wlp/bin/server", "run"]
CMD ["defaultServer"]

Соберём образ:

docker build -t app . 

Запустим его как контейнер:

docker run -d --name app -p 9080:9080 app

Проверим полученный результат http://localhost:9080/health/



Для остановки контейнера:

docker stop app

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

Как меняется специфика работы?


Комплектация


Образ контейнера должен собираться только один раз, а затем выполняется во всех средах. Поэтому рекомендуется собирать каждое приложение вместе c сервером приложений. Это упрощает жизненный цикл и развертывание приложений и отлично вписывается в современный мир контейнерных технологий.

Сборка


Сейчас уже не нужно упаковывать разные технические блоки в отдельные архивы. Вся бизнес-логика вместе с веб-сервисами и сквозным функционалом упаковывается в один war-файл. Это значительно упрощает установку проекта, а также процедуру сборки. Больше не приходится упаковывать приложение в виде нескольких уровней иерархии, чтобы затем снова распаковать его в один экземпляр сервера.

Запуск


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

Расширение функционала


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

Зачем упаковывать сервер приложений в контейнер?


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

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

Больше практики вы найдете здесь
На сайте проекта помимо документации есть большое количество обучающих руководств: как создавать web-приложения с maven/gradle, упаковывать и разворачивать приложения, разворачивать и настраивать микросервисы в kubernetes, управлять трафиком с помощью istio, выполнять развертывание в IBM Cloud, у других популярных облачных провайдеров и многом другом.

Себастьян Дашнер (Java & OSS энтузиаст, Java Champion, IBMer, JCP member, Jakarta EE committer) в своем блоге публикует полезные статьи о том, как пользоваться OpenLiberty, например, мониторинг Open Liberty с помощью Prometheus и Grafana, а его книга Architecting Modern Java EE Applications использовалась при подготовки этой статьи.

Liberty-maven-plugin (альтернатива для gradle) может заметно упростить вашу работу. Кстати, в руководствах есть хорошие примеры его использования.

Вы также можете внести свой вклад в проект.

Комментарии (0)