В каких случаях для коммуникации микросервисов стоит выбрать Apache Kafka?

Ответ

Apache Kafka — это не просто очередь сообщений, а распределенная стриминговая платформа. Её стоит выбирать, когда в основе архитектуры лежат потоки событий (event streams) и требуется их надежная обработка и хранение.

Ключевые сценарии использования:

  1. Event-Driven архитектура и Event Sourcing: Когда необходимо иметь долговечный, реплицируемый и перечитываемый лог всех событий в системе. Kafka позволяет сервисам подписываться на события и реагировать на них, а также восстанавливать свое состояние, перечитав топик с самого начала.

  2. Высоконагруженная аналитика и сбор метрик: Для сбора и обработки больших потоков данных в реальном времени, таких как кликстрим, логи, данные с IoT-устройств.

  3. Асинхронная коммуникация и слабая связанность: Для decoupling'а (развязывания) сервисов. Продюсеру не нужно знать о консьюмерах и ждать их ответа. Это повышает отказоустойчивость системы.

  4. Агрегация логов: Централизованный сбор логов со всех микросервисов в одном месте для дальнейшего анализа.

  5. Репликация данных: Для синхронизации данных между различными хранилищами или дата-центрами.

Пример отправки сообщения на Go (библиотека sarama):

// Создаем синхронного продюсера, который ждет подтверждения от брокера
producer, err := sarama.NewSyncProducer([]string{"kafka:9092"}, nil)
if err != nil {
    log.Fatalln("Failed to start Sarama producer:", err)
}
defer producer.Close()

msg := &sarama.ProducerMessage{
    Topic: "user-events",
    Value: sarama.StringEncoder("User registered with id 123"),
}

// Отправляем сообщение и получаем partition/offset
partition, offset, err := producer.SendMessage(msg)
if err != nil {
    log.Printf("FAILED to send message: %sn", err)
} else {
    log.Printf("Message sent to partition %d at offset %dn", partition, offset)
}

Когда Kafka может быть избыточен:

  • Для простых синхронных RPC-вызовов (лучше gRPC/REST).
  • В системах, где нужна сложная логика маршрутизации сообщений (RabbitMQ может подойти лучше).
  • В небольших проектах, где накладные расходы на поддержку кластера Kafka неоправданны.

Ответ 18+ 🔞

Так, слушай, смотри, про Кафку. Это ж не какая-то там простая очередь, куда кинул и забыл, нет, блядь. Это, сука, распределённая стриминговая платформа, ёпта! Ты её всерьёз брать должен, когда у тебя вся архитектура на потоках событий стоит, и их надо хранить, обрабатывать и не потерять ни одного, как последнюю надежду.

Короче, когда она реально нужна:

  1. Архитектура на событиях и Event Sourcing: Вот когда тебе надо, чтобы был пиздец какой надёжный, реплицированный лог всех событий, который можно перечитать с любого места. Сервисы подписались, реагируют, а если всё накрылось — просто отмотал лог назад и восстановился, как ни в чём не бывало. Красота, блядь!

  2. Высоконагруженная аналитика в реальном времени: Клики, логи, данные с этих ваших умных чайников — всё это летит овердохуищным потоком, а Кафка всё проглатывает, не поперхнувшись.

  3. Чтобы сервисы не знали друг о друге: Продюсер отправил событие и пошёл дальше пить кофе. Ему похуй, кто и как его съест. Консьюмеров может быть ноль или сто — продюсеру всё равно. Связанность слабая, отказоустойчивость — огонь.

  4. Сбор логов со всей этой микросервисной зоопарки: Вместо того чтобы рыскать по каждому контейнеру, ты всё централизованно в Кафку сгребаешь и потом уже разбираешься.

  5. Репликация данных между хранилищами или дата-центрами: Чтобы всё было синхронно, как часы, а не как попало.

Вот, смотри, как на Go отправить (библиотека sarama):

// Создаем синхронного продюсера, который ждет подтверждения от брокера
producer, err := sarama.NewSyncProducer([]string{"kafka:9092"}, nil)
if err != nil {
    log.Fatalln("Failed to start Sarama producer:", err)
}
defer producer.Close()

msg := &sarama.ProducerMessage{
    Topic: "user-events",
    Value: sarama.StringEncoder("User registered with id 123"),
}

// Отправляем сообщение и получаем partition/offset
partition, offset, err := producer.SendMessage(msg)
if err != nil {
    log.Printf("FAILED to send message: %sn", err)
} else {
    log.Printf("Message sent to partition %d at offset %dn", partition, offset)
}

А теперь, внимание, когда она НЕ НУЖНА, чтобы зря голову не морочить:

  • Для простых синхронных вызовов по типу «спросил-получил». Тут тебе не Кафка, а обычный gRPC или REST, ебать его в сраку.
  • Если нужна сложная маршрутизация сообщений, условные «топики на стероидах». Тут, может, RabbitMQ лучше подойдёт, эта мартышлюшка похитрее будет в таких делах.
  • В маленьких проектах, где поднимать и содержать целый кластер Кафки — это как из пушки по воробьям, нахуй не нужно и дорого. Терпения ебать ноль, а возни — овердохуя.