Как реализовать систему отслеживания онлайн-статуса пользователей?

Ответ

Реализация индикатора онлайн-статуса в распределенной системе — это задача управления состоянием (presence management). Простого HTTP-запроса недостаточно, так как он не поддерживает постоянное соединение.

Правильная архитектура выглядит так:

1. Основная технология: WebSockets

Пользователь считается онлайн, пока у него активно WebSocket-соединение с сервером. Это обеспечивает постоянный канал связи.

2. Архитектура отслеживания

  1. Подключение (Connect):

    • Когда пользователь устанавливает WebSocket-соединение, сервер (Connection Gateway) аутентифицирует его и получает userID.
    • Сервер записывает информацию о том, что пользователь онлайн, в быстрое хранилище. Идеально для этого подходит Redis.
    • Команда в Redis: SADD online_users <userID> (добавляем ID пользователя в множество).
  2. Отключение (Disconnect):

    • Graceful: Если пользователь сам закрывает соединение, сервер получает событие onClose и удаляет его из Redis: SREM online_users <userID>.
    • Ungraceful (обрыв связи): Соединение может оборваться без уведомления (пропал интернет, закрылся ноутбук). Для этого нужен механизм Heartbeat (пульс).
  3. Механизм Heartbeat:

    • Сервер периодически (например, каждые 30 секунд) отправляет клиенту ping сообщение по WebSocket.
    • Клиент, получив ping, должен немедленно ответить pong.
    • Если сервер не получает pong в течение заданного таймаута (например, 45 секунд), он принудительно закрывает соединение и считает пользователя оффлайн, удаляя его из Redis.
  4. Проверка статуса:

    • Чтобы узнать, онлайн ли конкретный пользователь, любой другой сервис может сделать быстрый запрос в Redis: SISMEMBER online_users <userID>.
    • Эта операция имеет сложность O(1), что делает её чрезвычайно эффективной.

3. Оповещение об изменении статуса

Когда статус пользователя меняется (онлайн/оффлайн), сервер может опубликовать это событие в брокер сообщений (NATS, RabbitMQ). Другие пользователи, которые являются его друзьями или находятся с ним в одном чате, могут быть подписаны на эти события и мгновенно получать обновления в своем интерфейсе.