Статьи

Миграция сервера приложений: с JBoss EE5 на Wildfly EE7

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

Если вы используете Java EE 5, есть большая вероятность, что вы используете один из этих серверов:

Есть много других серверов, поддерживающих Java EE 5, и вы можете проверить их здесь .

прелюдия

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

Когда мы решили перевести одно из наших критически важных приложений с Java EE 5 на 7, мы столкнулись с дилеммой, какой сервер приложений использовать. Поскольку я занимал должность технического менеджера, теперь я мог влиять на это решение. В итоге мы выбрали Wildfly по следующим причинам:

  • Реализован Java EE 7 Полный профиль
  • Мощный CLI для управления сервером
  • Команда, уже знакомая с реализациями Java EE, поставляемыми с Wildfly

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

стратегия

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

В любом случае, при работе над проектом миграции вы можете следовать двум стратегиям:

Функция Freeze

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

комбинированный

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

Первые шаги

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

Инструменты поддержки, которые вы используете, могут также нуждаться в обновлении. Плагины Maven для нового сервера, развертывания Jenkins, все, что взаимодействует с сервером приложений. Это сложная задача, поскольку сложность управления всей этой дополнительной средой и ветвями не так проста.

Ходить по Пути

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

загрузки классов

Если вы не NoClassDefFoundError ClassNotFoundException , NoClassDefFoundError или ClassCastException вы можете захотеть сыграть в лотерею и выиграть!

Это особенно верно с JBoss 4.x Classloader. В то время загрузка классов была (до сих пор, но даже более чем) дорогой операцией, поэтому JBoss использовал нечто, называемое UnifiedClassLoader . Это означало, что между приложениями не было настоящей изоляции. EAR-архивы могут просматривать друг друга для загрузки библиотек. Конечно, это было главной головной болью, чтобы справиться. Хуже всего было, когда вам приходилось развертывать приложение на клиенте, используя сервер JBoss . Если вы не управляете им, текущее развертывание может конфликтовать с вашим собственным.

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

При смене серверов это наиболее распространенные проблемы, связанные с загрузкой классов:

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

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

Если вы используете Dependency Plugin, это ваш друг, и вы можете использовать mvn dependency:tree и mvn dependency:analyze чтобы помочь вам.

Wildfly также предоставляет вам специальный файл дескриптора jboss-deployment-structure.xml который позволяет вам точно настроить загрузку классов, добавляя или удаляя зависимости или изменяя поведение загрузчика классов. Вот пример:

JBoss развертывания-структура

01
02
03
04
05
06
07
08
09
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?>
<jboss-deployment-structure xmlns="urn:jboss:deployment-structure:1.2">
    <ear-subdeployments-isolated>false</ear-subdeployments-isolated>
    <deployment>
        <dependencies>
            <module name="org.jboss.msc" export="true"/>
            <module name="org.jboss.as.naming" export="true"/>
            <module name="org.jboss.as.server" export="true"/>
            <module name="deployment.app-client.jar" export="true"/>
            <module name="deployment.app-ear.ear.app-entity.jar" export="true"/>
        </dependencies>
    </deployment>
</jboss-deployment-structure>

Этот пользовательский дескриптор добавляет зависимости из других развертываний, а именно app-client.jar и даже дополнительного развертывания другого EAR в app-ear.ear.app-entity.jar .

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

Общая конфигурация

В JBoss 4.x вся конфигурация была распределена по разным файлам: server.xml , jboss-service.xml , login-config.xml и многим другим. Вам пришлось вручную редактировать файлы, чтобы изменить необходимую конфигурацию. Это была утомительная работа, особенно когда у вас не было доступа к серверу, и вам пришлось задокументировать набор изменений, которые кто-то другой должен выполнить.

В Wildfly большая часть конфигурации идет в файл configuration/standalone.xml , но я никогда не редактирую файл. Wildfly поставляется с очень мощным интерфейсом командной строки (CLI), который позволяет вам писать практически все изменения, которые необходимо выполнить на сервере. Вот пример конфигурации Undertow:

undertow.cli

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
/subsystem=undertow/server=default-server/ajp-listener=ajp:add(socket-binding=ajp)
  
/subsystem=undertow/server=default-server/host=app \
 :add( \
 alias=["localhost, ${app.host}"] \
 )
  
/subsystem=undertow/server=default-server:write-attribute(name="default-host", value="app")
  
/subsystem=undertow/server=default-server/host=app/filter-ref=server-header:add
/subsystem=undertow/server=default-server/host=app/filter-ref=x-powered-by-header:add
/subsystem=undertow/server=default-server/host=app/location="/":add (\
 handler=welcome-content)
  
/subsystem=undertow/server=default-server/host=default-host/filter-ref=server-header:remove
/subsystem=undertow/server=default-server/host=default-host/filter-ref=x-powered-by-header:remove
  
:reload
  
/subsystem=undertow/server=default-server/host=default-host/location="/":remove
  
/subsystem=undertow/server=default-server/host=default-host:remove
  
/subsystem=undertow/server=default-server/host=segurnet/setting=single-sign-on:add(path="/")
  
:reload

Это настройка виртуального хоста с именем app , делающая его хостом по умолчанию, удаляет хост по умолчанию, который поставляется с Wildfly, и активирует единый вход.

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

Источники данных

В JBoss 4.x для настройки источника данных требуется только скопировать драйвер базы данных в папку lib и создать файл *-ds.xml с подробной информацией о соединении с источником данных.

В Wildfly это немного сложнее, но не имеет большого значения. Вы настраиваете источник данных как модуль, а затем можете использовать интерфейс командной строки для добавления сведений о соединении с источником данных в конфигурацию сервера. В прошлом я даже написал целый пост в блоге об этом: настройка источника данных JBoss / Wildfly с Maven .

Безопасность

Безопасность в JBoss 4.x была настроена в conf/login-config.xml . В Wildfly было внесено не так много изменений, но если вам нужно реализовать пользовательский модуль входа, зависимости изменились. Я также написал целый пост в блоге об этом: Custom Principal и LoginModule для Wildfly .

Привязки JNDI

@LocalBinding в JBoss 4.x использовалось @LocalBinding для определения точного имени JNDI для вашего EJB. Но Java EE 7 ввел стандартные имена JNDI по объему, что означает, что вы должны следовать соглашению для поиска EJB.

Вместо:

Локальная привязка

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
@Stateless
@Local(UserBusiness.class)
@LocalBinding(jndiBinding="custom/UserBusiness")
public class UserBusinessBean implements UserBusiness {}
  
...
  
private UserBusiness userBusiness;
  
try {
    InitialContext context = new InitialContext();
    userBusiness = (UserBusiness) context.lookup("custom/userBusiness");
} catch(Exception e) {
  
}

Ты сможешь:

EJB 3.1 Связывание

1
2
@EJB(lookup="java:global/app-name/app-service/UserBusinessBean")
private UserBusiness userBusiness;

Когда Wildfly запускается, вы также можете проверить стандартные привязки в журнале:

Wildfly JNDI Стандартные крепления

1
2
3
4
5
6
java:global/segurnet/segurnet-protocol-gu-ejb/UserBusinessBean!com.criticalsoftware.segurnet.protocol.gu.ejb.business.UserBusiness
 java:app/app-service/UserBusinessBean!com.app.business.UserBusiness
 java:module/UserBusinessBean!com.app.business.UserBusiness
 java:global/app-name/app-service/UserBusinessBean
 java:app/app-service/UserBusinessBean
 java:module/UserBusinessBean

Другие вещи

Это более конкретные темы, о которых я также писал в блоге, и они могут быть также интересны:

Заключительные слова

Как уже говорилось, миграции никогда не идут прямым путем. Тем не менее, есть несколько вещей, которые вы можете сделать, чтобы улучшить. Пишите тесты, тесты и тесты. Я уже говорил вам писать тесты? Сделайте это, прежде чем работать с любым материалом миграции. Даже если все с миграцией выглядит нормально, вы можете столкнуться с небольшими изменениями поведения между различными версиями реализаций Java EE.

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

Мой последний совет: если вы сидите в старой версии Java EE, вам обязательно нужно выполнить миграцию. Загляните в мой блог о сокращении Legacy от Java EE 5 до 7 . Переход не простой, но с каждой новой версией Java EE и заботой о стандартизации каждое обновление должно становиться все менее болезненным.

Ссылка: Миграция сервера приложений: от JBoss EE5 к Wildfly EE7 от нашего партнера по JCG Роберто Кортеса в блоге