Spring Boot series 21 Spring Websocket реализует обсуждение кластерного решения websocket

Spring Boot Spring RabbitMQ WebSocket

Обзор

В данной статье рассматривается схема кластера вебсокетов:

  1. В кластере веб-сокетов серверная часть точно отправляет указанное сообщение указанному пользователю, а внешний интерфейс получает сообщение, отправленное службой, в режиме реального времени.
  2. Обсудите варианты кластеризации веб-сокетов и определите лучший вариант

Кластерное решение веб-сокета

Анализ кластерного плана

这里写图片描述

в последнем сообщении в блогеSpring Boot Series 20 Реализация Spring Websocket отправляет сообщения указанным пользователямФункция отправки сообщений указанным пользователям реализована в , но при кластеризации сервисов, предоставляющих сервисы websocket (как показано на рисунке выше), возникают следующие проблемы:

На приведенном выше рисунке пользователь A регистрируется в службе A через веб-сокет, служба A подписывается на сообщения в RabbitMQ через протокол STOMP, а пользователь B — то же самое. Если пользователь A подключен к службе A, даже если модуль MQ в службе B отправляет сообщение пользователю A с использованием экземпляра SimpMessagingTemplate, сообщение не может быть доставлено пользователю A, поскольку в службе B нет регистрационной информации службы A, поэтому оно не может достичь пользователя А. Точное push-сообщение. Сообщение будет доставлено пользователю А только в том случае, если модуль MQ в службе А отправит сообщение этому пользователю с помощью экземпляра SimpMessagingTemplate.

В ответ на эту проблему мы решим эту проблему с помощью 3 решений и подробно проанализируем недостатки каждого решения.

кластерное решение webSocket 1

ОбзорНезависимо от того, к какой службе подключен получатель сообщения, каждая служба A/B получает сообщение и использует экземпляр SimpMessagingTemplate для отправки одного и того же сообщения, чтобы гарантировать, что одно сообщение всегда будет получено пользователем.

这里写图片描述

Подробный процесс выглядит следующим образом:

  1. Пользователь A/B подключается к службе A/B через ws соответственно, а затем служба A/B обращается к RabbitMQ через протокол stomp.
  2. Отправитель сообщения отправляет сообщение на обмен RabbitMQ, используя обмен секторами. Это гарантирует, что одно и то же сообщение может быть получено службой A/B одновременно.
  3. После того, как модули MQ в двух службах получат соответствующие сообщения, независимо от того, подключены ли соответствующие пользователи к RabbitMQ через себя, они напрямую используют экземпляр SimpMessagingTemplate для отправки сообщений пользователям, указанным в сообщениях.
  4. Пользователь A/B получает соответствующее сообщение

преимущество:

  1. Реализация относительно проста

недостаточный:

  1. Переключатель RabbitMQ, который производитель сообщения отправляет, должен быть широковещательной функцией, такой как переключатель сектора.
  2. Чтобы сообщение беспрепятственно дошло до пользователя, одно и то же сообщение должно выполнять одну и ту же операцию в обеих службах A/B. Таким образом, чем больше сервисов, тем больше сообщений будет отправлено повторно.
  3. Если пользователь не в сети, независимо от того, сколько сообщений отправлено, пользователь не может их получить.

кластерное решение webSocket 2

ОбзорИспользуйте Redis для кэширования информации о подключении пользователя к веб-сокету, запишите, в какую службу входит пользователь, когда приходит сообщение, отправьте сообщение в службу, в которую входит пользователь, а затем используйте экземпляр SimpMessagingTemplate для отправки службы.

这里写图片描述

На основе Схемы 1 добавляются следующие функции:

  1. Модуль MQ добавляется в службу A/B, а модуль MQ службы A/B будет подключен к RabbitMQ и подпишется на очередь A/B соответственно.
  2. Служба A/B добавляет модуль WS.Когда подключается веб-сокет, информация о подключении пользователя сохраняется в Redis, и система запоминает, в какую службу входит каждый пользователь.
  3. Производитель сообщения отправляет сообщение на биржу, а не напрямую в службу A/B.
  4. Добавлен новый модуль отправки, который получает сообщение, затем читает сообщение от redis, чтобы отправить его на сервер, к которому подключается пользователь, а затем отправляет сообщение в очередь, соответствующую службе подключения пользователя. Если сообщение должно быть отправлено пользователю B, модуль отправки отправит сообщение в очередь B.
  5. После того как модуль MQ службы A/B получает сообщение, он использует экземпляр SimpMessagingTemplate для передачи сообщения указанному пользователю.

преимущество:

  1. Это решение устраняет недостатки предыдущего решения.

недостаток

  1. сложный в реализации
  2. 1x количество раз для отправки сообщений MQ

кластерное решение webSocket 3

ОбзорВместо использования SimpMessagingTemplate используйте клиентский API RabbitMQ для отправки сообщений непосредственно в очереди, на которые подписаны пользователи RabbitMQ.

Обнаружено, что когда пользователь входит в вебсокет через браузер и регистрирует RabbitMQ, это соединение создаст очередь в RabbitMQ, имя очереди похоже на stomp-subscription-***, эта очередь привязана к обмен по умолчанию amq.topic, а ключ маршрутизации — «имя очереди веб-подписки+'-user'+websocket sessionId" (здесь demo-userpjplggbl, demo — это имя очереди соединения stomp weboscket, значение websocket sessionId при входе pjplggbl к входу в websocket), картина следующая:

这里写图片描述

В соответствии с этим разработана следующая архитектура:

这里写图片描述

На основе схемы 1 сделаны следующие модификации, и схема новой архитектуры выглядит следующим образом:

  1. Служба A добавляет модуль WS. Когда веб-сокет подключается, информация о подключении пользователя (в основном значение веб-сокета sessionId) сохраняется в Redis
  2. Обмен, на который производители сообщений отправляют сообщения, эти сервисы не проталкивают сервис A/B напрямую.
  3. Добавьте новую отправку модуля, этот модуль получает отправленную информацию и читает сообщение от Redis, чтобы получить значение sessionId websocket, соответствующее пользователю, а затем вычисляет ключ маршрутизации, соответствующий пользователю, в соответствии с вышеуказанными правилами, а затем отправляет сообщение пользователю, на которого подписано в очереди
  4. передний конец получить сообщение

преимущество:

  1. То есть преодолеть недостатки первой схемы, а она проще второй схемы

В заключение

Лучшее решение — вариант 3. В следующей статье мы расскажем, как реализовать вариант 3 в коде.