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