Socket.io с несколькими серверами без липких сессий - PullRequest
0 голосов
/ 24 апреля 2020

У нашего клиента очень специфичная c архитектура, которая ограничивает возможности подключения. Это чатбот с React и NodeJS, который использует Socket.IO для наших веб-сокетов. В верхней части серверов сокетов есть обязательный HAProxy, настроенный для использования циклического распределения нагрузки, поэтому клиент будет каждый раз подключаться к другому серверу сокетов. Приложение отлично работает с одним экземпляром Socket, но когда добавляется второй экземпляр, мы замечаем, что события сокета поступают в каждый экземпляр случайным образом, и ответное событие возвращается клиенту лишь в небольшом проценте случаев.

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

Мы используем redis-адаптер, как, например,

this.io.adapter(this.redis({ host: this.redis_host, port: this.redis_port, password: this.redis_password }));

Io использует транспорты: ['websocket', 'polling'], но мы попробовали каждую их комбинацию.

Мы также используем комнаты как таковые:

  1. Клиентский интерфейс подключается и имеет уникальный идентификатор
  2. Сервер добавляет клиента в комнату с идентификатором в качестве его имени
  3. Сервер добавляет запросы в очередь для обработки работником. client
  4. Рабочий клиент принимает запросы и отправляет ответ на любой сервер с идентификатором в своем теле
  5. Сервер использует идентификатор для отправки ответа на номер этого идентификатора

Клиент внешнего интерфейса добавляется в комнату при инициализации:

initialize() {
    this.io.on(this.SocketConstants.CONNECTION, (client) => {
        const UniqueId = this.getId(client)
        client.join(UniqueId);
      }

Ответ рабочего отправляется в комнату:

client.on(this.SocketConstants.SEND_TO, async (data) => {
      this.io.to(data.UniqueId).emit(this.SocketConstants.RESPONSE, data);
    });

Возможно ли это вообще сделать sh? Как мне убедиться, что Redis правильно делит сокеты ID и комнаты между серверами?

...