> В каких случаях лучше использовать брокер сообщений для взаимодействия между сервисами (Go)

Уровень: senior · Роль: backend · Язык: Go · Категория: Технические вопросы

Компании: Wildberries

Стек: Go

> Пример ответа

Короткий ответ

Брокер сообщений оправдан при асинхронной, слабосвязанной коммуникации между сервисами: фоновые задачи, fan-out события, буферизация пиковых нагрузок, гарантированная доставка и отказоустойчивость. Для синхронных запрос-ответных взаимодействий с низкой задержкой (например, API gateway → backend) лучше использовать HTTP/gRPC. Ключевой критерий - нужна ли вам немедленная обработка результата или можно отложить её без потери бизнес-логики.

Подробное объяснение

Брокер сообщений (RabbitMQ, Kafka, NATS) решает задачи, которые HTTP-вызовы решают плохо:

  • Асинхронность и развязывание по времени - producer не ждёт ответа, consumer может обработать позже. Это критично для email-рассылок, генерации отчётов, обработки медиа.
  • Множественные потребители - одно событие (например, order.created) может потреблять несколько сервисов независимо: аналитика, уведомления, инвентаризация. С HTTP пришлось бы делать N вызовов или оркестрацию.
  • Буферизация и сглаживание пиков - брокер выступает очередью: при всплеске запросов сервисы не падают, а накапливают сообщения и обрабатывают их в своём темпе.
  • Гарантия доставки - брокер хранит сообщения до подтверждения от consumer (ack), что невозможно при простом HTTP POST.
  • Retry и dead-letter - встроенные механизмы повторной обработки и карантина для ошибочных сообщений.
  • Backpressure - consumer сам контролирует скорость потребления, не блокируя producer.

Не стоит использовать брокер, когда:

  • нужен синхронный ответ (например, проверка баланса перед оплатой) - здесь брокер добавит задержку и сложность;
  • трафик низкий и нет требований к гарантиям доставки - проще REST;
  • требуется строгий порядок обработки с транзакционностью - брокер не даёт ACID, нужна идемпотентность и компенсация.

В Go с брокером часто работают через библиотеки: github.com/segmentio/kafka-go, github.com/rabbitmq/amqp091-go, github.com/nats-io/nats.go.

На практике

Типичные сценарии в Go-микросервисах:

  • Event-driven архитектура - сервис заказов публикует события, остальные подписываются. Это даёт слабую связанность: добавление нового потребителя не требует изменения producer.
  • Задачи с долгим выполнением - конвертация файлов, отправка push-уведомлений. HTTP-запрос вернёт 202 Accepted, а реальная работа уйдёт в очередь.
  • Интеграция с внешними системами - брокер как буфер между нашим сервисом и медленным/нестабильным внешним API.
  • CQRS и materialized views - команды пишут в основную БД, события через брокер обновляют read-модели.

Важно проектировать контракты сообщений версионированными (например, event.v1), предусматривать идемпотентность consumer (повторная доставка возможна), и настраивать мониторинг очередей (lag, error rate).

Пример кода

Пример публикации и потребления в Go с RabbitMQ:

GO
// producer
func publishOrderCreated(ch *amqp.Channel, order Order) error {
body, _ := json.Marshal(order)
err := ch.Publish(
"orders", // exchange
"order.created", // routing key
false, false,
amqp.Publishing{
ContentType: "application/json",
Body: body,
DeliveryMode: amqp.Persistent,
},
)
return err
}
// consumer
func consumeOrderCreated(ch *amqp.Channel) {
msgs, _ := ch.Consume(
"orders_queue", "", false, false, false, false, nil,
)
for msg := range msgs {
var order Order
if err := json.Unmarshal(msg.Body, &order); err != nil {
msg.Nack(false, true) // retry
continue
}
processOrder(order)
msg.Ack(false)
}
}

Как отвечать на собеседовании

Начните с чёткого разделения: синхронное vs асинхронное взаимодействие. Приведите 2-3 конкретных сценария из практики, где брокер решал проблему (пиковая нагрузка, множественные подписчики, гарантия доставки). Упомяните trade-off: сложность эксплуатации, необходимость идемпотентности, отсутствие транзакций. Если спросят про Kafka vs RabbitMQ - сравните по модели потребления (log vs queue), порядку сообщений, throughput.

Покажите, что понимаете, когда брокер - антипаттерн: например, для CRUD-операций с немедленным ответом. Хорошо добавить про backpressure и dead-letter - это признак senior-уровня.

Что проверяет интервьюер

  • Понимание разницы между синхронной и асинхронной коммуникацией.
  • Умение обосновать выбор инструмента под конкретные требования (latency, reliability, throughput).
  • Знание паттернов: event-driven, competing consumers, publish-subscribe.
  • Понимание ограничений брокеров: отсутствие транзакций, возможные дубликаты, сложность отладки.
  • Практический опыт: как вы проектировали контракты, обрабатывали ошибки, настраивали retry.

Типичные ошибки

  • Предлагать брокер для всего подряд - без анализа требований к задержке и синхронности.
  • Игнорировать идемпотентность - не учитывать, что сообщение может прийти дважды.
  • Не упоминать dead-letter и мониторинг - признак отсутствия production-опыта.
  • Путать Kafka и RabbitMQ - не понимать, что Kafka - это лог с offset, а RabbitMQ - очередь с ack.
  • Забывать про версионирование событий - при изменении структуры сообщения ломаются все потребители.
  • Утверждать, что брокер гарантирует порядок - в общем случае это не так, нужен partitioning или single queue.

> ГОТОВЫ К СЛЕДУЮЩЕМУ СОБЕСЕДОВАНИЮ?

Запустите тренировочную сессию с ИИ и получите детальную обратную связь, чтобы увереннее проходить реальные интервью