Чат в реальном времени в масштабе

Чат в реальном времени в масштабе
Чат в реальном времени в масштабе

Я искал различные решения для крупномасштабных чатов. Мне кажется, что я понимаю 90% этого, но я обращаюсь к этому форуму, чтобы связать себя узами брака.

Я представляю себе запуск нескольких серверов сообщений за балансировщиком нагрузки, поддерживающих долговременные соединения с клиентом (wss или xmpp). Количество серверов может масштабироваться горизонтально в зависимости от входящих запросов. Затем на серверной части сообщения распространяются по шаблону pub-sub. Это означает, что если два клиента пытаются общаться, но подключены к разным серверам, то об этом позаботится система обмена сообщениями pub-sub.

Пока во всем есть смысл. Изображение ниже прекрасно это иллюстрирует.

Но я не могу себе представить, как каждому серверу WebSocket удается подписаться на все темы, которые будет обрабатывать сервер PubSub (redis).

Я представляю, как сервер PubSub обрабатывает 100 000 запросов в секунду посредством сегментирования. Но я не могу понять, как каждый сервер WebSocket обрабатывает подписки. Потому что подписка на все темы во всех сегментах не будет заливать каждый сервер WebSocket?

Итак, как только мы пойдем по пути сегментирования, как нам правильно распространять сообщения? Потому что тогда нам нужен некоторый интеллект, чтобы каждый сервер WebSocket был подписан на правильные темы, в которых клиент A и клиент B отправляют свои сообщения. Каким-то образом каждый сервер WebSocket должен постоянно подписываться/отменять подписку в зависимости от того, какая тема используется для клиента A и клиента B.

Или на самом деле серверы WebSocket могут быть подписаны на КАЖДУЮ тему? Я ошибаюсь, рассматривая это как проблему? Если да, то зачем вообще использовать балансировку нагрузки?

Редактировать: черпая вдохновение из здесь и здесь

Редактировать 2: перефразировать.

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

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

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

Эти правила связаны с горизонтальным масштабированием. Обычно правила масштабирования системы тесно связаны с балансировщиком нагрузки. В конце концов, вам нужно, чтобы они были похожи, или как только балансировщик нагрузки скажет «о, этот узел слишком занят», у него не будет другого узла, на который можно перенаправить запрос. Если такая конфигурация произойдет, существующие узлы будут загружены до тех пор, пока они не выровняются.

С логической точки зрения поставить в очередь каждый сервер WebSocket (сокращенно WSS) для каждой возможной темы невозможно, поскольку это ограничено аппаратными возможностями.

Соединение или сокет, полученный для данного WSS, идентифицирует клиента как часть исходной транзакции. Черты личности этого клиента указывают на интересы конкретного клиента, например, на какие темы подписываться.

Сценарий реализации 1

Когда клиент делает запрос, он регистрируется в данном WSS для этого соединения.

Скорее всего, у вас будет какая-то форма широкомасштабного push-уведомления от PubSub на уровень WSS, чтобы сказать: «Произошло какое-то событие». Только когда событие получено от PubSub, WSS будет смотреть глубже. Затем оттуда можно будет создать целевой запрос к PubSub. Вы бы использовали «долгоживущие» соединения, чтобы понять, какой запрос написать. Каждое долгоживущее соединение представляет определенного клиента. Этот клиент привязывается к темам, которые представляют интерес.

Например, предположим, что клиент А отправил сообщение. WSS, указанный 2-3, подтолкнет это к PubSub 3-4. WSS, на который указывает 4-5, получит широкое событие «Изменение». Затем WSS 4-5 спрашивал PubSub, если что-то изменилось в интересах Клиента Б.

Если PubSub 3-4 скажет «нет», вы тут же закончите расследование.

Теперь отступим. WSS 2-3 и 4-5 поддерживают 500 клиентов каждый. Клиент 1 отправляет сообщение. WSS 2-3 и 4-5 оба получают свое push-уведомление «Что-то изменилось». WSS 2-3 и 4-5 отправят запрос с соответствующими идентификаторами клиентов.

PubSub отправит ответ, ориентированный на соответствующих клиентов. Скорее всего, чтобы уменьшить болтливость ответа, он объединит несколько уведомлений о событиях в одно. Почему? Если, скажем, 50 клиентов подписались на одну и ту же тему, зачем повторять одни и те же данные еще 49 раз?

После этого соответствующий WSS отправляет уведомления соответствующим клиентам.

Сценарий реализации 2

Когда клиент делает запрос, он регистрируется в данном WSS для этого соединения.

WSS для этого клиента отправляет событие регистрации в PubSub 3-4. PubSub 3-4 должен отслеживать все эти отдельные пары WSS/Client. Каждое событие, отправляемое в PubSub 3-4, должно проверять эти пары и отправлять события соответствующим образом.

Это оказывает более сильное влияние на PubSub 3-4 и может даже потребовать от вас реализовать для него вертикальное масштабирование.

Клиент А отправляет сообщение. WSS 2-3 отправляет событие в PubSub. PubSub интерпретирует сообщение и дополнительно извлекает контекст, связанный с подпиской клиентов. Затем анализирует список целей WSS для получения push-уведомления и отправляет уведомление на WSS 4-5.

WSS 4-5 получает push-уведомление для общей темы и пересылает его клиенту B.

Сделав шаг назад, WSS 2-3 и 4-5 поддерживают по 500 клиентов каждый. Клиент 1 из 2-3 отправляет сообщение. 50 клиентов подписаны на ту же тему. PubSub 3-4 анализирует интересы и отправляет соответствующие push-уведомления.

После этого соответствующий WSS отправляет уведомления соответствующим клиентам.

Комментарии и дополнительные вопросы

Оба сценария реализации имеют свои преимущества и недостатки.

Теперь вопрос к вам. Когда нагрузка падает и происходит горизонтальное сжатие, как балансировщик нагрузки перераспределяет открытые сокеты из отброшенного WSS? Как это изменение распространяется по линии?


LetsCodeIt, 19 декабря 2022 г., 06:22