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

Producer
Émet des événements dans un topic.
Consumer
Lit et traite les messages depuis un topic.
Partition
Unité de parallélisme d’un topic.
Offset
Position du message dans la partition.
Consumer Group
Groupe de consommateurs partageant un topic de manière parallèle.
Dead Letter Queue (DLQ)
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).

Bonnes pratiques :
  • 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
}
    
Patrons de résilience :
  • 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.

Navigation de la Formation

Review My Order

0

Subtotal