Frog Proger 25 октября 2024

🔫🎯 Выстрелил и забыл: 3 основные стратегии отправки сообщений в Kafka

Какой подход обеспечит вашему проекту идеальный баланс производительности и гарантии доставки: рискованная стратегия «Выстрелил и забыл» или продвинутая асинхронная отправка?
🔫🎯 Выстрелил и забыл: 3 основные стратегии отправки сообщений в Kafka
Этот материал взят из нашей еженедельной email-рассылки, посвященной бэкенду. Подпишитесь, чтобы быть в числе первых, кто получит дайджест.

Существует три основных подхода к отправке сообщений, и каждый представляет собой определенный компромисс между надежностью, производительностью и сложностью реализации:

  1. «Отправить и забыть».
  2. Синхронная отправка.
  3. Асинхронная отправка.

Разберем нюансы, преимущества и недостатки каждого из этих подходов.

«Отправить и забыть»

Как работает

        ProducerRecord<String, String> record = new ProducerRecord<>("topic-1", "msg", "kafka trial message");
try {
     producer.send(record);
} catch(Exception e) {
     e.printStackTrace();
}

    
Kafka Producer отправляет сообщение в Kafka Broker, но не получает подтверждения от брокера о том, что сообщение было доставлено и записано в соответствующую тему
Kafka Producer отправляет сообщение в Kafka Broker, но не получает подтверждения от брокера о том, что сообщение было доставлено и записано в соответствующую тему

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

Однако, если произойдет более серьезный сбой (например, сбой сети или поломка узла брокера), сообщение может быть утеряно, и система об этом не узнает.

Плюсы

  • Высокая производительность – отправка сообщений не блокирует поток программы, и система может отправлять сообщения с максимальной скоростью.
  • Простота реализации – не требуется обрабатывать ответы или ошибки от брокера.

Минусы

  • Риск потери сообщений – если что-то пойдет не так, сообщение может не дойти до брокера или быть потеряно, и программа об этом не узнает.
  • Отсутствие контроля – мы не получаем информацию о том, куда было отправлено сообщение и было ли оно доставлено.

Когда использовать

Когда потеря сообщений не является критичной. Это может быть допустимо для задач, где небольшая потеря данных не приведет к серьезным последствиям. Например:

  • Логи – если несколько логов будут утеряны, это не будет критично.
  • Данные сенсоров – если из тысяч данных с датчиков несколько не будут доставлены, система все равно сможет корректно работать.

Синхронная отправка

Как работает

        ProducerRecord<String, String> record = new ProducerRecord<>("topic-1", "msg", "kafka trial message");
try {
     producer.send(record).get();
} catch(Exception e) {
     e.printStackTrace();
}

    
Каждый вызов блокирует выполнение программы, пока не будет получено подтверждение
Каждый вызов блокирует выполнение программы, пока не будет получено подтверждение

В синхронной отправке после вызова метода send() программа блокируется и ожидает подтверждения от Kafka, что сообщение было доставлено. Как только подтверждение получено, программа продолжает работу. Если подтверждение не получено или произошла ошибка, вызывается исключение.

Плюсы

  • Надежность – если какие-то действия нужно выполнять только в случае успешной доставки сообщения, и ни в каком другом случае, то эта стратегия обеспечит такую меру.
  • Простота реализации – этот подход реализовать гораздо проще, чем асинхронный.

Минусы

  • Снижение производительности – если брокеры перегружены или сеть работает медленно, это может существенно замедлить работу системы.
  • Отсутствие гибкости – система становится менее эффективной в условиях высоких нагрузок, так как каждая отправка ждет ответа перед продолжением работы.

Когда использовать

Когда каждое сообщение имеет критическое значение, и вам необходимо быть уверенным, что оно доставлено. Во всех остальных случаях лучше использовать другие подходы.

💻 Библиотека программиста
Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека программиста»

Асинхронная отправка

Как работает

        ProducerRecord<String, String> record = new ProducerRecord<>("topic-1", "msg", "new kafka async");
try {
		producer.send(record, new DemoProducerCallback());
} catch(Exception e) {
		e.printStackTrace();
}

    
В коллбэке можно записать подтверждение в лог или попробовать отправить сообщение снова в случае ошибки
В коллбэке можно записать подтверждение в лог или попробовать отправить сообщение снова в случае ошибки

Асинхронная отправка похожа на стратегию «отправить и забыть», с той лишь разницей, что вы используете функцию обратного вызова для обработки подтверждения или ошибок от Kafka. Программа не блокируется, как при синхронной отправке, но при этом есть возможность обработать успешное подтверждение или ошибку в коллбэке.

Плюсы

  • Хорошая производительность – программа не блокируется для каждой отправки сообщения. Сообщения отправляются быстро, что важно для высоконагруженных систем.
  • Обработка ошибок – есть механизм для обработки возможных проблем, и вы не теряете контроль над процессом отправки.

Минус

  • Сложнее в реализации – необходимо писать код для обработки callback-функций, что добавляет сложности, особенно если нужно детально обрабатывать всевозможные ошибки или подтверждения.

Когда использовать

Это наиболее универсальная стратегия, которая подходит для большинства высоконагруженных и распределенных систем, где важно одновременно обеспечивать высокую производительность и надежность. Например:

  • Обработка заказов в системах электронной коммерции, где нужна высокая производительность, но вы также хотите быть уверены, что каждый заказ доставлен.
  • Системы с высокими нагрузками (например, социальные сети или аналитические системы), где нужно быстро обрабатывать большой объем сообщений, но при этом отслеживать возможные ошибки.

Подведем итоги

В большинстве случаев рекомендуется использовать асинхронную отправку – она обеспечивает оптимальный баланс между производительностью и надежностью. «Отправить и забыть» подходит для систем, где потеря сообщений не критична, а синхронную отправку стоит использовать только в том редком случае, когда нужно абсолютное подтверждение доставки, а производительностью можно пожертвовать.

***

Какую стратегию отправки сообщений вы используете в своих проектах и почему?

Комментарии

ВАКАНСИИ

Добавить вакансию
Разработчик C++
Москва, по итогам собеседования

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ