Как бы вы спроектировали систему групповых чатов?

Ответ

Это классическая задача на system design. Решение зависит от масштаба, но можно выделить два уровня: базовый и масштабируемый.

1. Базовая реализация (в рамках одного сервера)

Для простого чата можно использовать паттерн Издатель-Подписчик (Pub/Sub) с помощью горутин и каналов.

// ChatRoom управляет подписчиками и рассылкой сообщений
type ChatRoom struct {
    name      string
    clients   map[chan<- string]bool // Подписчики (каналы для отправки)
    broadcast chan string            // Канал для входящих сообщений
    join      chan chan<- string     // Канал для подключения нового клиента
    leave     chan chan<- string     // Канал для отключения клиента
}

// run - основной цикл жизни чат-комнаты
func (cr *ChatRoom) run() {
    for {
        select {
        case client := <-cr.join:
            cr.clients[client] = true
        case client := <-cr.leave:
            delete(cr.clients, client)
            close(client)
        case msg := <-cr.broadcast:
            for client := range cr.clients {
                client <- msg // Рассылаем сообщение всем подписчикам
            }
        }
    }
}
  • Плюсы: Простота, нет внешних зависимостей.
  • Минусы: Не масштабируется, нет персистентности (история чата теряется при перезапуске), все клиенты должны быть подключены к одному серверу.

2. Масштабируемая архитектура

Для высоконагруженного приложения нужна распределенная система:

  1. Протокол связи: WebSockets для постоянного двунаправленного соединения между клиентом и сервером.
  2. Connection Gateway: Шлюз соединений, который терминирует WebSocket-соединения от пользователей. Это может быть отдельный сервис, написанный на Go.
  3. Брокер сообщений (Message Broker): Сердце системы. Когда пользователь отправляет сообщение, Gateway-сервис публикует его в топик брокера (например, chat.room_id.messages). Все остальные Gateway-сервисы, у которых есть подписчики на этот чат, получают сообщение и пересылают его своим клиентам.
    • Примеры: NATS, RabbitMQ, Kafka.
  4. Сервис Чатов (Chat Service): Управляет логикой комнат, участниками, правами доступа.
  5. Хранение данных:
    • История сообщений: NoSQL база данных, оптимизированная для записи и временных рядов. Например, Cassandra или ClickHouse.
    • Информация о чатах и пользователях: Реляционная БД (например, PostgreSQL).
  6. Кеширование: Redis для хранения сессий, онлайн-статусов пользователей и другой часто запрашиваемой информации.