Как построить масштабируемый обмен сообщениями в чате в реальном времени с помощью Websocket? - PullRequest
0 голосов
/ 24 апреля 2020

Я пытаюсь построить в режиме реального времени (приватный) чат между пользователями видеоигр с 25K + одновременными подключениями. В настоящее время мы используем 32 узла, где пользователи могут подключаться через балансировщик нагрузки. Проблема, которую я пытаюсь решить, состоит в том, как направить сообщения каждому пользователю?

В настоящее время мы используем socket.io & socket.io-redis, где каждый websocket соединяет комнату со своим идентификатором пользователя, и мы посылаем каждое сообщение, которое они должны получить в эту комнату. Проблема этого дизайна в том, что мы достигли пределов Redis Pubsub и Socket.io, которые плохо масштабируются (socket.io отправляет сообщения на все узлы, которые проверяют, подключен ли пользователь, это нежизнеспособно).

Наш текущий стек состоит из Postgres, Redis & RabbitMQ. Я много думал об этой проблеме и нашел 3 разных решения:

  • Маршрутизация всех сообщений с помощью RabbitMQ. Когда пользователь подключается, мы создаем обмен с разветвлением типа с идентификатором пользователя и очередью для каждого подключения к веб-сокету (мы должны обрабатывать несколько подключений на пользователя). Когда мы хотим передать этому пользователю, мы просто публикуем sh для этого обмена. Проблема такого подхода заключается в том, что нам нужно создать много очередей, и я слышал, что это может быть не очень эффективно.
  • Создайте очередь для каждого узла в RabbitMQ. Когда пользователь подключается, мы сохраняем ID узла и сокета в наборе Redis, поэтому, когда нам нужно отправить сообщение этому указанному c пользователю, мы сначала получаем список узлов, отправляемых в очередь каждого узла, которая затем обрабатывать маршрутизацию к указанному c клиенту в приложении. Проблемы с этим подходом состоят в том, что в случае сбоя узла мы можем хранить информацию о том, что пользователь подключен, а это не так. Чтобы исправить это, нам нужно было бы прекратить запись Redis пользователей, но это не идеальное исправление. Кроме того, если позже мы захотим внедрить групповой чат, это будет означать, что нам нужно отправлять дубликаты сообщений в Rabbit, это не идеально.
  • Go все вместе с Firebase Cloud Messaging. У нас есть мобильное приложение, и мы планируем использовать его для уведомлений pu sh, когда пользователь не подключен, но будет ли оно подходящим, даже если пользователь подключен?

Что Как вы думаете, лучше всего подходит для нашего случая использования? У вас есть другая идея?

1 Ответ

0 голосов
/ 27 апреля 2020

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...