JGroups — это программное обеспечение Bela Ban для надежного обмена сообщениями, которое легко настраивается и может использовать TCP или UDP в качестве транспортного протокола. В основном — вы запускаете JGroups на нескольких клиентах, они образуют кластер и могут отправлять и получать сообщения внутри кластера.
JGroups используется внутри JBoss Infinispan. Infinispan, однако, в отличие от JGroups добавляет семантику распределенного кэша (реплицированные / распределенные режимы, аннулирование записей, поведение транзакций, API доступа к карте и т. Д.). Он даже позволяет использовать кластер в качестве вычислительной сетки.
Infinispan, в свою очередь, используется для обеспечения функциональности кластеризации JBoss AS 7. Следовательно, это означает, что базовая подсистема JGroups может и настраивается с использованием стандартного автономного файла * .xml JBoss AS 7. Вы можете получить доступ к кэшу Infinispan из компонента Java EE (например, EJB) без каких-либо проблем, как описано здесь .
Однако бывают случаи, когда вы хотите использовать только базовый обмен сообщениями JGroups вместо всей семантики кэша, которую вам предоставляет Infinispan. И вот тут-то все становится сложнее. Вы всегда можете использовать JGroups напрямую и сохранить конфигурацию для него как локальные ресурсы приложения. Это может стать предметом спора, если это является нарушением спецификации Java EE, которая гласит, что приложение не должно управлять низкоуровневыми подключениями, порождать потоки, открывать сокеты и т. Д. Это лучше оставить на усмотрение сервер приложений — он также позволяет нам использовать один файл конфигурации вместо того, чтобы распространять его по нескольким местам. Итак, вопрос — как получить доступ к подсистеме JGroups из нашего EJB-приложения? Все решение включает в себя несколько шагов, которые будут описаны ниже. Если вы хотите проверить весь рабочий проект — взгляните на мой проект JGroups AS7 Github .
1. Написать пользовательский сервисный активатор JBoss AS 7
Этот активатор ( JGroupsChannelServiceActivator.java
) будет делать две вещи:
- создать реальный канал JGroups, используя конфигурацию протокола JBoss,
- привязать вновь созданный канал JGroups к JNDI.
Первая часть сделана в JGroupsChannelServiceActivator#createChannel(-)
. Я не знаю ни ServiceActivator, ни других внутренних компонентов модулей JBoss AS 7, но из того, что вы можете прочитать:
1
2
3
4
5
6
|
InjectedValue<ChannelFactory> channelFactory = new InjectedValue<>(); ServiceName serviceName = ChannelFactoryService.getServiceName(STACK_NAME); ChannelService channelService = new ChannelService(CHANNEL_NAME, channelFactory); target.addService(channelServiceName, channelService) .addDependency(serviceName, ChannelFactory. class , channelFactory).install(); |
кажется, что он создает новый сервис ( ChannelService
) и позволяет JBoss MSC автоматически внедрять свой зависимый ChannelFactory
во время установки. ChannelFactory
будет использовать стек протокола UDP. Вторая часть выполняется в JGroupsChannelServiceActivator#bindChannelToJNDI(-)
и связывает вновь созданный экземпляр Channel
с JNDI в определенном пользователем месте. В нашем случае это java:jboss/channel/myChannel
.
2. Зарегистрируйте Активатор
Теперь нам нужно сказать JBoss AS 7, чтобы он вызвал наш пользовательский активатор. Это делается с использованием стандартизированного API JDK ServiceLoader . В двух словах это означает, что нам нужно предоставить файл META-INF/services/org.jboss.msc.service.ServiceActivator
с полным именем нашего класса-активатора. Посмотрите на этот пример .
3. Добавьте необходимые модули в наше приложение
Итак, у нас есть активатор, который должен творить чудеса. Если мы попытаемся развернуть его как таковой, мы получим несколько исключений ClassNotFoundException . Это потому, что модули JBoss. Наше приложение не содержит все эти артефакты JBoss, такие как JGroups, ServiceActivator API и JNDI-связанные классы. Мы не хотим загромождать наше приложение этими библиотеками — мы просто хотим определить зависимости от модулей, предоставляемых самой JBoss AS 7. Мы делаем это в META-INF/jboss-deployment-structure.xml
. Обратите внимание, что мы могли бы сделать это в разделе MANIFEST.MF Dependencies: но Intellij IDEA, похоже, не работает с сгенерированным Maven файлом MANIFEST.MF :
01
02
03
04
05
06
07
08
09
10
|
<? xml version = '1.0' encoding = 'UTF-8' ?> < jboss-deployment-structure > < deployment > < dependencies > < module name = 'org.jgroups' /> < module name = 'org.jboss.as.naming' /> < module name = 'org.jboss.as.clustering.jgroups' /> </ dependencies > </ deployment > </ jboss-deployment-structure > |
Модули JGroups необходимы для доступа к JChannel, ChannelService и т. Д. Модуль именования необходим для кода привязки JNDI.
4. Разработайте EJB, используя канал JGroups.
JGroupsSampleDataProducer
— это Singleton EJB, который показывает, как получить доступ к каналу JGroups. Это довольно просто из-за привязки JNDI. Мы можем просто использовать:
1
2
|
@Resource (lookup = 'java:jboss/channel/myChannel' ) private JChannel channel; |
и вот оно. Этот EJB регистрирует таймер, который вызывается каждые 2 секунды и отправляет некоторое случайное строковое сообщение.
Обратите внимание, что нам не нужно было явно запускать JChannel
. Мы просто вводим его и сразу используем. Посмотрите на ChannelService
используемый в нашем активаторе с шага 1. Его метод запуска выглядит так:
1
2
3
4
5
6
7
8
|
@Override protected void start() throws Exception { (...) if ( this .channel.getProtocolStack().findProtocol(STATE_TRANSFER. class , STATE. class , STATE_SOCK. class ) != null ) { this .channel.connect( this .id, null , STATE_TRANSFER_TIMEOUT); } else { this .channel.connect( this .id); } |
Так что этот сервис будет подключаться к нашему каналу автоматически . Вместо использования ChannelService
мы могли бы разработать наш собственный сервис, который будет отвечать за запуск и остановку нашего канала, или мы могли бы даже передать эту ответственность фактическому пользователю канала.
5. Разверните EJB-JAR
Теперь мы готовы развернуть наше приложение на сервере JBoss AS 7. Самая важная часть здесь — убедиться, что наш сервер будет работать с соответствующей конфигурацией, то есть с определенным стеком протоколов JGroups. Это делается с использованием <subsystem xmlns='urn:jboss:domain:jgroups:1.1'>
. Я использую JBoss AS 7.1.1 и конфигурацию standalone-full-ha.xml
.
** Примечание: ** Поскольку Intellij IDEA не позволяет вам легко изменять файл конфигурации для вашей JBoss AS, как это делает Eclipse, нам нужно будет указать его с помощью параметров VM: -Djboss.server.default.config=standalone-full-ha.xml
.
Нам также необходимо убедиться, что JGroups будет использовать IPv4 (иногда он выбирает IPv6, что может привести к некоторым странным и трудным для решения проблем). Для этого добавьте параметр -Djava.net.preferIPv4Stack=true
в конфигурацию сервера.
6. Запустите клиентское приложение
Вы можете найти довольно простой клиентский код здесь . Он просто подключается к кластеру JGroups, используя указанный файл конфигурации. Помните, что для номера порта и адреса многоадресной рассылки должны быть установлены одинаковые значения для сервера и клиента. Также не забудьте добавить параметр -Djava.net.preferIPv4Stack=true
виртуальной машины во время работы вашего клиента. Надеюсь, вы найдете этот урок полезным и сэкономит вам время на настройку. Огромное спасибо Бела Пан за много важных советов и Полу Ферраро за то, что он указал мне на соответствующие темы форума (как этот или этот ) относительно подобных проблем.
Ссылка: Использование JGroups напрямую из компонента JBoss AS 7 от нашего партнера по JCG Петра Новицки в блоге Петра Новицкого на домашней странице .