Wildfly — связь между двумя веб-сокетами на отдельных узлах?

Мы разрабатываем приложение, которое будет включать некоторые элементарные функции чата/передачи сообщений. Веб-приложение развернуто на Wildfly 8.x и использует стандартные библиотеки JavaEE 7 (в отличие от дополнительной среды приложений, такой как Spring). Для этого мы используем веб-сокеты, поскольку нам нужна функция push-to-browser. обеспечивает. Однако мы развертываем это веб-приложение в кластерной/HA конфигурации. Если пользователь А подключен к узлу А и передает сообщение, предназначенное для пользователя Б, подключенного к узлу Б, как мы осуществляем транспортировку этого сообщения?

В конфигурации с одним узлом простым ответом будет поддержка статического Map или List, в котором есть все веб-сокеты и сеансы, и маршрутизация к соответствующему веб-сокету в зависимости от адресата сообщения. Но с более чем одним узлом это, очевидно, не будет работать, потому что статические Map/List относятся к JVM.

Как бы мы подошли к достижению этой цели? Можно ли использовать JMS и заставить каждый Websocket действовать как прослушиватель JMS? Какое влияние это окажет на использование ресурсов или масштабируемость и производительность?

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


person Shadowman    schedule 23.05.2014    source источник


Ответы (3)


Вы можете сделать это двумя способами

1) Вы можете создать отдельный push-сервис на другом веб-сервере, заставить издателя и подписчика слушать этот сервис. Используйте эту службу push в качестве брокера, то есть всякий раз, когда издатель будет готов с данными для отправки, он отправит их в эту службу, после чего брокер получит широковещательные данные для всех подписчиков.

2) Вы можете создать очередь JMS на отдельной JVM, заставить издателя и подписчика слушать эту службу. Используйте эту службу JVM в качестве брокера.

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

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

person Hari    schedule 27.05.2014

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

Преимущества:

  • легко реализовать
  • легко настроить (один и тот же источник данных на каждом узле)
  • быстро
  • супер масштабируемый
  • не будет инфраструктурным кошмаром
  • легко контролировать
  • транзакционный (в отличие от некоторого общекластерного кеша)

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

person Yuri    schedule 27.05.2014
comment
Хотя это сработает, производительность и масштабируемость будут ужасными. Не говоря уже о том, что это потребует постоянного опроса БД на наличие новых сообщений. - person Shadowman; 29.05.2014
comment
Я когда-то работал над проектом с похожей настройкой: каждый из 6 узлов кластера дважды в секунду опрашивал БД; Производительность БД вообще не была проблемой. Обратите внимание, что это не было на высокопроизводительном оборудовании. Также при таком подходе было бы проще добавить отложенную доставку и связь «многие ко многим». - person Yuri; 29.05.2014
comment
более того, если вы настроили тему jms, чтобы избежать опроса базы данных, почему бы не отправить сообщение чата напрямую в jms вместо уведомления? - person Gab; 30.05.2014
comment
Уведомление может быть для 100-го сообщения или по тайм-ауту или в зависимости от того, что наступит раньше. Я против одного сообщения JMS на одно сообщение чата. Это может породить огромное количество сообщений JMS; не говоря уже о том, что если транзакции включены, будет 2 на сообщение. Но с помощью одного обращения к БД вы можете получить все, что вам нужно; пиковая нагрузка более предсказуема. - person Yuri; 02.06.2014

Самый простой способ, вероятно, - использовать встроенную систему связи кластера, при этом вы останетесь горизонтально масштабируемым:

https://docs.jboss.org/author/display/WFLY8/HTTP+Services

http://www.jgroups.org/tutorial/html/ch02.html

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

Я все равно никогда не использовал такие функции, я полагаю, что мультикаст должен поддерживаться сетью.

person Gab    schedule 28.05.2014