Spring Boot & Kafka — Architecture Événementielle Pro
Producers, consumers, topics, partitions, parallélisme, Strategy Pattern, résilience et bonnes pratiques pour construire une architecture événementielle moderne et scalable.
Introduction
Kafka n’est plus un simple broker de messages : c’est devenu un pilier des architectures distribuées, des microservices event-driven et des pipelines temps réel. Couplé à Spring Boot, il permet d’implémenter des systèmes robustes, scalables et découplés.
Ce chapitre couvre la maîtrise des producteurs, des consommateurs, du parallélisme, des partitions, du Strategy Pattern pour router les événements et des mécanismes de résilience industrielle.
Lexique essentiel
Émet des événements dans un topic.
Lit et traite les messages depuis un topic.
Unité de parallélisme d’un topic.
Position du message dans la partition.
Groupe de consommateurs partageant un topic de manière parallèle.
Topic dédié aux messages en erreur.
1. Configuration Kafka avec Spring Boot
Spring Boot simplifie fortement la configuration Kafka grâce aux propriétés dédiées.
spring.kafka.bootstrap-servers=localhost:9092
spring.kafka.consumer.group-id=order-group
spring.kafka.consumer.auto-offset-reset=earliest
spring.kafka.producer.key-serializer=org.apache.kafka.common.serialization.StringSerializer
spring.kafka.producer.value-serializer=org.springframework.kafka.support.serializer.JsonSerializer
spring.kafka.consumer.value-deserializer=org.springframework.kafka.support.serializer.JsonDeserializer
Producer professionnel
@Service
@RequiredArgsConstructor
public class OrderProducer {
private final KafkaTemplate<String, OrderCreatedEvent> template;
public void send(OrderCreatedEvent event) {
template.send("order.created", event.orderId().toString(), event);
}
}
Consumer robuste
@Component
@RequiredArgsConstructor
public class OrderConsumer {
private final OrderService service;
@KafkaListener(topics = "order.created", groupId = "order-group")
public void consume(OrderCreatedEvent event) {
service.handleOrderCreated(event);
}
}
👉 Le consumer doit être léger : juste un routeur vers le domaine. 👉 Toute la logique métier → dans un service.
2. Consommations parallèles & partitions
Kafka traite les messages en parallèle via les partitions : 1 partition = 1 flux séquentiel. Pour paralléliser → créer plusieurs partitions + consumer group.
Déclaration d’un topic partitionné
@Bean
public NewTopic orderCreatedTopic() {
return TopicBuilder.name("order.created")
.partitions(6)
.replicas(1)
.build();
}
Parallélisme via @KafkaListener
@KafkaListener(
topics = "order.created",
groupId = "order-group",
concurrency = "6"
)
public void consume(OrderCreatedEvent e) { ... }
👉 concurrency = nombre de threads 👉 Il doit correspondre au nombre de partitions (ou moins).
- 1 consumer = 1 partition (max throughput).
- Concevoir vos consumers idempotents.
- Jamais de traitement lourd dans le consumer → déléguer au service.
3. Strategy Pattern — Router les événements proprement
Quand un même consumer doit traiter plusieurs types d’événements, le code devient vite illisible. La solution professionnelle : Strategy Pattern.
Interface générique
public interface EventHandler<T> {
void handle(T event);
String type();
}
Implémentation métier
@Component
class OrderCreatedHandler implements EventHandler<OrderCreatedEvent> {
@Override
public void handle(OrderCreatedEvent event) {
// ...
}
@Override
public String type() {
return "order.created";
}
}
Registry automatique
@Component
@RequiredArgsConstructor
class EventDispatcher {
private final List<EventHandler<?>> handlers;
public void dispatch(String type, Object event) {
handlers.stream()
.filter(h -> h.type().equals(type))
.findFirst()
.ifPresent(h -> h.handle(event));
}
}
👉 Résultat : architecture lisible, extensible, testable.
4. Résilience & gestion des erreurs
Une architecture Kafka doit résister aux erreurs, aux timeouts et à la charge. Spring Kafka + Resilience4j permettent de créer des systèmes robustes.
Retry automatique
spring.kafka.listener.ack-mode=record
spring.kafka.listener.concurrency=6
spring.kafka.listener.retry.max-attempts=3
Dead Letter Queue (DLQ)
@Bean
public DeadLetterPublishingRecoverer recoverer(KafkaTemplate<Object, Object> template) {
return new DeadLetterPublishingRecoverer(template);
}
Timeouts & Circuit Breaker (Resilience4j)
@Retry(name = "orderRetry")
@CircuitBreaker(name = "orderCB")
public void handle(OrderCreatedEvent event) {
// traitement métier
}
- Retry court pour erreurs temporaires
- Circuit Breaker pour services instables
- DLQ pour messages irrécupérables
- Idempotence obligatoire
Quiz : Spring Kafka
-
Q1. Quelle structure permet de paralléliser ?
- A. topic
- B. partition ✔
- C. offset
-
Q2. Quel pattern permet de router des événements ?
- A. Singleton
- B. Builder
- C. Strategy Pattern ✔
Exercice d’application
Implémentez un flux complet :
— Producer “order.created”
— Consumer avec parallélisme
— Strategy Pattern pour router 2 événements différents
— DLQ + retry
— Métriques d’observabilité des consommations
Résumé
Spring Boot & Kafka permettent de bâtir des systèmes événementiels performants et scalables. En combinant producers, consumers parallélisés, Strategy Pattern, DLQ, retry et observabilité, vous obtenez une architecture robuste, extensible et prête pour la production.
