Многие современные веб-сайты имеют события, которые отображаются у пользователя в режиме реального времени без перезагрузки страницы. Например, в любой социальной сети нет необходимости перезагружать страницу, чтобы получить новое сообщение от другого пользователя. Как технически устроены такие системы?
Современная архитектура выглядит следующим образом:
- веб-браузер подключается к серверу по веб-сокету (особый тип соединения, который один раз устанавливается и держится. В рамках этого соединения клиент с сервером общаются независимо)
- когда происходит событие, back-end отправляет данные браузеру по веб-сокету
- браузер получает данные и отображает событие в режиме реального времени
Нас интересует back-end часть данной архитектуры. Обычно веб-сокет соединения обслуживаются отдельным микросервисом. Когда со стороны веб-сервера происходит событие, сервер отправляет данные в веб-сокет микросервиса, чтобы передать веб-браузеру.
Как передавать данные от веб-сервера в веб-сокет микросервис? Самое тривиальное решение: делать HTTP запрос. Для небольших приложений с редкими событиями этого будет достаточно. Однако для большинства проектов такое решение не подойдет, потому что HTTP устанавливает TCP соединение на каждом запросе и отправляет много лишней информации в виде заголовков. Например, в мессенджерах, где новые сообщения приходят миллионами, с HTTP все будет работать недопустимо медленно.
В данном случае хорошим решением будет использование брокера сообщений. Он может быть настроен под разные модели доставки сообщений. В примере с мессенджерами идеально подходит модель Pub/Sub (издатель-подписчик). Веб-сокет микросервис подписывается на канал личных сообщений пользователя. В какой-то момент веб-сервер публикует сообщение в канал, и веб-сокет микросервис отправляет его в браузер. Преимущества этого решения:
- подписчик держит постоянное соединение с брокером сообщений
- издатель отправляет только полезную информацию без лишних заголовков
- пропускная способность такого взаимодействия подходит для высоконагруженных проектов
Redis Pub/Sub
Разберем как Redis реализует модель Pub/Sub на примере личных сообщений в мессенджере.
Веб-сокет микросервис подписывается на события с помощью команды subscribe channel [channel ...]
:
127.0.0.1:6379> subscribe messages
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "messages"
3) (integer) 1
После выполнения команды возвращается 1 в случае успешной подписки на канал, и соединение блокируется в ожидании сообщений.
При отправке нового сообщения веб-сервер публикует событие в Redis командой publish channel message
:
127.0.0.1:6379> publish messages '{"user_id":55,"message_id":"d1356e62-f33f-412c-b47c-ff107f3e88b1","message_text":"Oh, hi Mark!","sent_at":1642741377}'
(integer) 1
В ответе на команду publish
возвращается количество клиентов, получивших опубликованное сообщение.
Со стороны веб-сокет микросервиса моментально приходит сообщение:
1) "message"
2) "messages"
3) "{\"user_id\":55,\"message_id\":\"d1356e62-f33f-412c-b47c-ff107f3e88b1\",\"message_text\":\"Oh, hi Mark!\",\"sent_at\":1642741377}"
1 означает действие; 2 — канал, из которого получено сообщение; 3 тело сообщения.
Когда использовать Pub/Sub
Стоит отметить, что Redis Pub/Sub используется в тех случаях, когда события могут быть потеряны. Если в момент публикации не будет ни одного подписчика или у пользователя не будет открытого веб-сокет соединения, событие уйдет в никуда. Например, это подходит для нотификаций пользователя о новых сообщениях в мессенджере, потому что при перезагрузке страницы данные будут получены с сервера по API. Однако данная архитектура явно не подходит для отправки уведомлений на электронную почту или SMS.
Резюме
- модель Pub/Sub используется в реалтайм приложениях
- Redis эффективно реализует модель Pub/Sub, позволяя иметь пропускную способность в 1 млн. сообщений в секунду
- подписчик подписывается на события командой
subscribe
- издатель публикует события командой
publish
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.