Мессенджер и онлайн-чат
Реалтайм-задача: спроектировать чат с мгновенной доставкой, статусами и историей.
WebSocket — постоянное двунаправленное соединение между клиентом и сервером, позволяющее серверу пушить сообщения клиенту без опроса (polling).
Требования
Функционально: отправить/получить сообщение в реальном времени, видеть статусы (доставлено/прочитано), presence (онлайн/офлайн), история переписки. Нефункционально: низкая латентность доставки, надёжность (сообщение не теряется), порядок сообщений в диалоге.
Транспорт: WebSocket
HTTP-опрос для чата неэффективен. WebSocket держит постоянное соединение: когда приходит сообщение для пользователя, сервер сразу пушит его в открытый сокет. Но соединения stateful — пользователь «висит» на конкретном узле.
Юзер A -- WS --> Gateway #2 -> [Очередь/маршрутизация] -> Gateway #5 -- WS --> Юзер BМаршрутизация и хранение
| Задача | Решение |
| Найти, на каком узле юзер | Реестр сессий (Redis: user -> gateway) |
| Получатель офлайн | Сохранить как недоставленное, доставить при входе |
| История сообщений | Колоночная БД (по диалогу + времени) |
| Порядок сообщений | Sequence id / timestamp на диалог |
Как работает под капотом
Поскольку WebSocket stateful, балансировка идёт по соединениям, а маршрутизация сообщения между пользователями требует знать, к какому gateway подключён получатель — это держат в общем реестре сессий. Доставку делают надёжной через подтверждения (ack) и хранение: сообщение сперва персистится, потом пушится; если получатель офлайн — лежит до подключения. Статусы (доставлено/прочитано) — это отдельные служебные события в обратную сторону. История диалогов хорошо ложится на колоночную БД с ключом «диалог + время».
Частые ошибки
- Опрос HTTP вместо WebSocket для реалтайма.
- Пушить сообщение без предварительного сохранения -> потеря при сбое.
- Игнорировать порядок сообщений и реестр сессий для маршрутизации.
Итог
- Реалтайм-доставка — через WebSocket; соединения stateful.
- Маршрутизация требует реестра сессий (user -> gateway).
- Сначала персист, потом push; офлайн-сообщения копятся до входа.