Ответ
Apache Kafka — распределенная потоковая платформа. Её применение должно быть обосновано архитектурными требованиями.
✅ Когда Kafka — хороший выбор:
- Обработка потоков событий в реальном времени: логи, телеметрия, клики.
- Высокая пропускная способность и горизонтальное масштабирование.
- Требуется гарантированная доставка и отказоустойчивость (репликация).
- Архитектура на основе событий (Event-Driven Architecture): декoupling сервисов.
- Необходимость повторной обработки данных (хранение сообщений длительное время).
❌ Когда Kafka — избыточна или не подходит:
- Простые синхронные RPC-вызовы между двумя сервисами (используйте REST/gRPC).
- Очереди задач (Job Queues) с одним потребителем на сообщение (рассмотрите RabbitMQ).
- Сценарии с очень низкой нагрузкой, где сложность администрирования Kafka не окупается.
- Требуется строгий глобальный порядок сообщений (Kafka гарантирует порядок только в пределах партиции).
- Транзакции, затрагивающие несколько источников данных (Sagas поверх Kafka сложны).
Пример Producer/Consumer:
// Producer
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("key.serializer", "org.apache.kafka.common.serialization.StringSerializer");
props.put("value.serializer", "org.apache.kafka.common.serialization.StringSerializer");
try (Producer<String, String> producer = new KafkaProducer<>(props)) {
producer.send(new ProducerRecord<>("user-events", "user123", "{"action":"login"}"));
}
// Consumer
Properties props = new Properties();
props.put("bootstrap.servers", "localhost:9092");
props.put("group.id", "my-group");
props.put("key.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
props.put("value.deserializer", "org.apache.kafka.common.serialization.StringDeserializer");
try (KafkaConsumer<String, String> consumer = new KafkaConsumer<>(props)) {
consumer.subscribe(List.of("user-events"));
while (true) {
ConsumerRecords<String, String> records = consumer.poll(Duration.ofMillis(100));
for (ConsumerRecord<String, String> record : records) {
System.out.println("Processed: " + record.value());
}
}
}
Выбор инструмента должен соответствовать задаче.