Ответ
По умолчанию Kafka работает неблокирующе, но поведение можно настроить в зависимости от требований.
1. Producer (отправка сообщений):
// АСИНХРОННАЯ отправка (не блокирует поток)
ProducerRecord<String, String> record = new ProducerRecord<>("topic", "key", "value");
producer.send(record, (metadata, exception) -> {
// Callback выполнится при получении подтверждения от брокера
if (exception != null) {
logger.error("Ошибка отправки", exception);
} else {
logger.info("Отправлено в partition {} offset {}",
metadata.partition(), metadata.offset());
}
});
// Продолжение выполнения кода без ожидания
// СИНХРОННАЯ отправка (блокирует поток до подтверждения)
try {
RecordMetadata metadata = producer.send(record).get(); // БЛОКИРУЮЩИЙ ВЫЗОВ
System.out.println("Отправлено: " + metadata.offset());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
2. Consumer (получение сообщений):
// НЕБЛОКИРУЮЩИЙ poll() с таймаутом
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
if (records.isEmpty()) {
// Нет сообщений - продолжаем работу
return;
}
for (ConsumerRecord<String, String> record : records) {
processMessage(record.value());
}
3. Современные реактивные подходы (Spring Kafka):
@Bean
public ReactiveKafkaConsumerTemplate<String, String> reactiveConsumer() {
return new ReactiveKafkaConsumerTemplate<>(receiverOptions);
}
// Реактивная обработка без блокировки
reactiveConsumer.receive()
.doOnNext(record -> {
System.out.println("Получено: " + record.value());
record.receiverOffset().acknowledge();
})
.subscribe();
Рекомендации:
- Используйте асинхронную отправку с callback для максимальной производительности
- Настройте
acks,retries,max.in.flight.requests.per.connectionдля баланса между надежностью и скоростью - Для потребителей используйте максимально короткие таймауты в
poll() - Рассмотрите реактивные реализации (Kafka Streams, Spring Reactor Kafka) для сложных пайплайнов обработки