Многие современные веб-сайты имеют события, которые отображаются у пользователя в режиме реального времени без перезагрузки страницы. Например, в любой социальной сети нет необходимости перезагружать страницу, чтобы получить новое сообщение от другого пользователя. Как технически устроены такие системы?
Современная архитектура выглядит следующим образом:
Нас интересует back-end часть данной архитектуры. Обычно веб-сокет соединения обслуживаются отдельным микросервисом. Когда со стороны веб-сервера происходит событие, сервер отправляет данные в веб-сокет микросервиса, чтобы передать веб-браузеру.
Как передавать данные от веб-сервера в веб-сокет микросервис? Самое тривиальное решение: делать HTTP запрос. Для небольших приложений с редкими событиями этого будет достаточно. Однако для большинства проектов такое решение не подойдет, потому что HTTP устанавливает TCP соединение на каждом запросе и отправляет много лишней информации в виде заголовков. Например, в мессенджерах, где новые сообщения приходят миллионами, с HTTP все будет работать недопустимо медленно.
В данном случае хорошим решением будет использование брокера сообщений. Он может быть настроен под разные модели доставки сообщений. В примере с мессенджерами идеально подходит модель 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 тело сообщения.
Стоит отметить, что Redis Pub/Sub используется в тех случаях, когда события могут быть потеряны. Если в момент публикации не будет ни одного подписчика или у пользователя не будет открытого веб-сокет соединения, событие уйдет в никуда. Например, это подходит для нотификаций пользователя о новых сообщениях в мессенджере, потому что при перезагрузке страницы данные будут получены с сервера по API. Однако данная архитектура явно не подходит для отправки уведомлений на электронную почту или SMS.
subscribe
publish
Вам ответят команда поддержки Хекслета или другие студенты.
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
Наши выпускники работают в компаниях:
Зарегистрируйтесь или войдите в свой аккаунт
Задавайте вопросы, если хотите обсудить теорию или упражнения. Команда поддержки Хекслета и опытные участники сообщества помогут найти ответы и решить задачу