Événements asynchrones
Comment fonctionnent les flux asynchrones basés sur les événements : publication, consommation et traitement entre microservices via l'Event Bus.
Qu’est-ce qu’un flux asynchrone basé sur les événements
Dans un flux asynchrone, un service publie un événement pour signaler que quelque chose s’est produit, et d’autres services réagissent à cet événement sans que le publicateur ait besoin d’attendre une réponse. Il n’existe aucune connexion directe entre celui qui produit l’événement et celui qui le consomme.
Ce modèle est fondamental dans les architectures distribuées car il permet un découplage temporel : les services n’ont pas besoin d’être disponibles en même temps pour communiquer.
Différence avec la communication synchrone
| Aspect | Synchrone | Asynchrone (événements) |
|---|---|---|
| Couplage | L’émetteur connaît le récepteur | L’émetteur ignore qui consomme |
| Disponibilité | Les deux doivent être actifs | Le consommateur peut traiter plus tard |
| Réponse | Immédiate | Aucune réponse directe |
| Scalabilité | Limitée par le récepteur le plus lent | Chaque consommateur scale indépendamment |
| Complexité | Moindre | Plus élevée (ordre, doublons, cohérence) |
Anatomie d’un événement
Un événement bien défini contient :
- Type : nom qui identifie ce qui s’est produit (
OrderPlaced,PaymentCompleted) - Payload : données pertinentes du fait (ID de la commande, montant, timestamp)
- Metadata : informations de traçabilité (correlationId, timestamp, source)
- Version : pour gérer l’évolution du schéma
{
"type": "OrderPlaced",
"version": "1.0",
"timestamp": "2024-01-15T10:30:00Z",
"correlationId": "abc-123-def",
"source": "ms-orders",
"payload": {
"orderId": "order-456",
"customerId": "cust-789",
"totalAmount": 150.00,
"items": [
{ "productId": "prod-001", "quantity": 2 }
]
}
}
Le cycle complet d’un événement
sequenceDiagram
participant MS1 as Microservicio Origen
participant EB as Event Bus
participant MS2 as Consumidor A
participant MS3 as Consumidor B
participant MS4 as Consumidor C
MS1->>EB: Publicar evento (OrderPlaced)
Note over MS1: El publicador continúa su trabajo
EB->>MS2: Entregar evento
EB->>MS3: Entregar evento
EB->>MS4: Entregar evento
MS2->>MS2: Actualizar inventario
MS3->>MS3: Enviar notificación
MS4->>MS4: Registrar analytics
Étape 1 : Publication
Le microservice d’origine achève son opération principale (par exemple, créer une commande) et publie un événement sur l’Event Bus. Une fois publié, le service n’attend pas que quiconque le traite.
Étape 2 : Distribution
L’Event Bus reçoit l’événement et le distribue à tous les consommateurs abonnés. Selon la technologie (Kafka, RabbitMQ, SNS/SQS), la distribution peut être :
- Fan-out : tous les abonnés reçoivent une copie
- Concurrence : un seul consommateur du groupe traite chaque message
- Combinaison : fan-out entre les groupes, concurrence au sein de chaque groupe
Étape 3 : Consommation
Chaque consommateur reçoit l’événement et exécute sa logique de manière indépendante. Un consommateur lent n’affecte pas les autres.
Étape 4 : Confirmation
Le consommateur confirme (acknowledge) qu’il a correctement traité l’événement. En cas d’échec, l’Event Bus peut réessayer la livraison.
Modèles de publication
Publier après la persistance
Le service enregistre d’abord dans sa base de données, puis publie l’événement. C’est simple, mais cela comporte un risque : si la publication échoue après la persistance, l’événement est perdu.
Outbox Pattern
Le service enregistre l’événement dans une table outbox au sein de la même transaction que l’opération métier. Un processus distinct lit la table outbox et publie les événements sur le bus. Cela garantit la cohérence entre l’opération et la publication.
Event Sourcing
Au lieu de sauvegarder l’état actuel, on sauvegarde tous les événements qui ont produit cet état. La publication est inhérente au modèle.
Défis des flux asynchrones
Ordre des événements
Les événements peuvent arriver dans un ordre différent de celui dans lequel ils ont été publiés. Les consommateurs doivent être capables de gérer cela, soit en réordonnant, soit en tolérant le désordre.
Événements dupliqués
L’Event Bus peut livrer le même événement plusieurs fois (at-least-once delivery). Les consommateurs doivent être idempotents : traiter deux fois le même événement doit produire le même résultat que de le traiter une seule fois.
Cohérence à terme
Les données entre services ne sont pas synchronisées instantanément. Après la publication d’un événement, un certain temps peut s’écouler avant que tous les consommateurs ne reflètent le changement. Le système doit être conçu pour tolérer cette fenêtre d’incohérence.
Observabilité
Suivre un flux asynchrone est plus difficile qu’un flux synchrone. Le correlationId est essentiel pour pouvoir suivre la chaîne d’événements à travers de multiples services.
Quand utiliser les événements asynchrones
Ils conviennent lorsque :
- Plusieurs services doivent réagir au même fait
- Aucune réponse immédiate n’est nécessaire
- On souhaite découpler les services pour les faire évoluer indépendamment
- Le processus peut tolérer une cohérence à terme
Ils ne conviennent pas lorsque :
- Une réponse immédiate est nécessaire pour l’utilisateur
- L’opération exige une cohérence forte entre les services
- La complexité ajoutée ne se justifie pas par le volume ou les exigences
Résumé
Les flux asynchrones basés sur les événements permettent aux services de communiquer sans couplage direct. Le publicateur ne connaît pas les consommateurs, et chaque consommateur traite à son propre rythme. Cela apporte scalabilité et résilience, mais introduit des défis d’ordre, de doublons et de cohérence qui doivent être abordés avec des modèles tels que l’idempotence, l’outbox et la traçabilité distribuée.