Веб-сокеты Tomcat на нескольких серверах

Текущее решение

У меня есть проблема с настройкой Java-сервера (Tomcat), и я надеюсь, что кто-то может дать некоторые рекомендации. В настоящее время мое веб-приложение представляет собой один сервер с серверной частью Java, работающей на Tomcat 8.5. Для обработки соединений Websocket я храню Map из всех javax.websocket.Session, переданных в методе onOpen().

@ServerEndpoint("/status")
public class StatusMessenger
{   
    private static ConcurrentHashMap<String, Session> sessions = new ConcurrentHashMap();

    @OnOpen
    public void onOpen(Session session) throws Exception
    {
        String sessionId = session.getRequestParameterMap().get("sessionId").get(0);
        sessions.put(session.getId(), session);
    }

Мое приложение рассылает сообщения только всем пользователям, поэтому broadcast() в моем коде просто перебирает sessions.values() и отправляет сообщение через каждый javax.websocket.Session.

public static void broadcast(String event, String message)
{
    for (Session session: sessions.values())
    {
       // send the message
    }
}
  1. Я даже не уверен, что это правильный способ обработки веб-сокетов в Tomcat, но он работал у меня годами, поэтому я предполагаю, что он приемлем.

Эта проблема

Теперь я хочу горизонтально масштабировать свое приложение на AWS на несколько серверов. По большей части мое приложение не имеет состояния, и я храню обычную информацию о сеансе HTTP в базе данных. Моя проблема заключается в том, что это статическое Map из javax.websocket.Session - оно не не имеет состояния, и на каждом сервере есть разные Map, каждый со своим собственным списком javax.websocket.Session.

В моем приложении серверный код в определенных ситуациях должен будет рассылать сообщение всем пользователям. Эти события могут произойти на любом сервере в этой конфигурации с несколькими серверами. Событие вызовет метод broadcast(), который перебирает javax.websocket.Sessions. Однако он будет проходить сеансы только в своем собственном Map.

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


person bluedevil2k    schedule 22.10.2020    source источник


Ответы (1)


Я нашел 2 альтернативных решения для этого...

  1. В моем балансировщике нагрузки я установил правило для маршрутизации всех путей с /{путь моего сервера веб-сокетов} на 1 сервер, чтобы все сеансы находились на одном сервере.

  2. Используйте стороннюю веб-библиотеку push-уведомлений, например Pusher (http://pusher.com).

person bluedevil2k    schedule 30.10.2020