Architecture de référence : event-driven / CQRS
Dans une architecture event-driven, les services publient des événements dans un journal d'événements (par ex. Kafka) au lieu de s'appeler directement, et les consommateurs les traitent de façon asynchrone. En partant de la construction de la dorsale d'événements, cet arbre parcourt pas à pas l'event sourcing (dériver l'état des événements), la séparation commande/requête avec CQRS, la projection du modèle de lecture, l'idempotence, la tolérance à la cohérence à terme et l'illusion de la « livraison exactly-once ». L'objectif est un système faiblement couplé et évolutif dont les compromis de cohérence sont bien compris.
Quelle décision devez-vous prendre dans votre architecture event-driven ?
Le fondement d'un système event-driven est un journal d'événements durable qui relie les services par des événements asynchrones. Construisez-vous encore la dorsale, voulez-vous dériver l'état des événements (event sourcing), ou séparez-vous les chemins de lecture et d'écriture (CQRS) ?
- Je construis la dorsale d'événements qui relie les services
- Je veux dériver l'état de l'historique des événements
- Je veux séparer les chemins de lecture et d'écriture (CQRS)
Comment construirez-vous le côté lecture en CQRS, et quelle est votre tolérance en matière de cohérence ?
En CQRS, les côtés commande (écriture) et requête (lecture) sont séparés ; les événements d'écriture mettent à jour la projection qui alimente le modèle de lecture. La question clé : pouvez-vous tolérer que le modèle de lecture soit en retard sur les écritures (cohérence à terme), ou attendez-vous que chaque événement soit traité exactement une fois ?
- J'alimenterai le modèle de lecture à partir des événements via une projection
- Les lectures doivent être à jour ; le retard est inacceptable
- Je veux que les événements soient traités « exactement une fois »
Recommandation : une dorsale de journal d'événements durable
Au centre d'une architecture event-driven se trouve un journal d'événements durable et ordonné dans lequel les producteurs écrivent et que les consommateurs lisent à leur propre rythme. Cette dorsale découple les services dans le temps et en échelle.
Recommandation : event sourcing (dériver l'état des événements)
En event sourcing, vous ne stockez pas l'état courant d'une entité mais tous les événements de modification (immuables) qui lui ont été appliqués ; l'état courant est dérivé en appliquant ces événements dans l'ordre. Cela fournit un historique d'audit complet et la possibilité de revenir à n'importe quel point du passé.
Recommandation : projection du modèle de lecture
En CQRS, le côté écriture produit des événements ; une projection écoute ces événements et met à jour un modèle de lecture optimisé pour les requêtes (vue dénormalisée). Les lectures sont servies depuis ce modèle prêt, entièrement séparé du chemin d'écriture, et les deux côtés montent en charge indépendamment.
Recommandation : concevez pour tolérer la cohérence à terme
Dans les systèmes event-driven/CQRS, le modèle de lecture est légèrement en retard sur les écritures (cohérence à terme). Plutôt que de chercher à « l'éliminer », concevez pour la tolérer ; isolez les quelques flux qui exigent une cohérence immédiate stricte.
Recommandation : idempotence (l'illusion de l'exactly-once)
En messagerie distribuée, la « livraison exactly-once » de bout en bout est en pratique une illusion ; les doublons de messages sont inévitables à cause du réseau et des nouvelles tentatives. Le bon objectif est un traitement idempotent : traiter deux fois le même événement doit donner le même résultat que le traiter une fois.