Documentation de l'architecture event-driven avec le modèle C4
L'architecture event-driven est devenue le standard pour construire des systèmes scalables et faiblement couplés. Les services publient des événements quand quelque chose se produit. D'autres services s'abonnent à ces événements et réagissent. Le producteur ne sait pas qui écoute. Le consommateur ne sait pas qui a publié. Le système est découplé, résilient et flexible.
Il est aussi quasiment invisible.
Quand vous regardez un diagramme C4 traditionnel d'un système event-driven, vous voyez des services avec des flèches pointant vers un message broker. Le Service A publie sur Kafka. Le Service B consomme depuis Kafka. Mais quels événements circulent entre eux ? Quel est le schéma ? Qui d'autre écoute ? Que se passe-t-il si un consommateur échoue ? Le diagramme montre la plomberie mais cache le comportement.
Documenter une architecture event-driven nécessite des techniques qui rendent l'invisible visible -- qui montrent non seulement l'infrastructure (brokers, queues, topics) mais les événements eux-mêmes, leurs flux, leurs schémas et leurs garanties. Ce guide couvre comment le faire en utilisant le modèle C4 et comment les fonctionnalités d'event channel d'Archyl font des systèmes event-driven des citoyens de premier plan dans votre documentation d'architecture.
Pourquoi les systèmes event-driven sont difficiles à documenter
L'architecture event-driven introduit plusieurs défis de documentation qui n'existent pas dans les systèmes synchrones request-response.
Flux de contrôle invisible
Dans un système synchrone, vous pouvez tracer une requête du client au serveur en suivant la chaîne d'appels. Le Service A appelle le Service B, qui appelle le Service C. Le flux de contrôle est explicite et visible dans le code.
Dans un système event-driven, le flux de contrôle est implicite. Le Service A publie un événement OrderCreated. Quelque part, le Service B réagit à cet événement en réservant de l'inventaire. Quelque part d'autre, le Service C réagit en envoyant un email de confirmation. Le Service A ne connaît ni B ni C. Le flux de contrôle est défini par les abonnements aux événements, pas par le code du producteur.
Cette indirection signifie que vous ne pouvez pas comprendre le comportement du système en lisant le code d'un seul service. Vous avez besoin d'une vue de plus haut niveau qui montre les flux d'événements à travers les services -- et cette vue est exactement ce que la documentation d'architecture devrait fournir.
Relations many-to-many
Dans les architectures synchrones, les relations sont typiquement one-to-one ou one-to-few. Le Service A appelle le Service B. La relation est directe et documentée par l'appel API.
Dans les architectures event-driven, les relations sont many-to-many. Un seul type d'événement peut avoir un producteur et cinq consommateurs. Un seul service peut consommer des événements de dix producteurs différents. Le graphe de relations est plus dense et plus complexe que dans les systèmes synchrones.
Les diagrammes d'architecture traditionnels peinent avec cette densité. Dessiner une flèche de chaque producteur à chaque consommateur à travers chaque topic crée un diagramme qui ressemble à un plat de spaghetti. Vous avez besoin d'une approche de documentation qui montre les flux d'événements au bon niveau d'abstraction.
Évolution des schémas
Les schémas d'événements évoluent dans le temps. L'événement OrderCreated peut commencer avec cinq champs et grandir à quinze sur deux ans. Les consommateurs peuvent dépendre de champs spécifiques. Les changements de schéma peuvent casser les consommateurs s'ils ne sont pas rétrocompatibles.
Documenter le schéma actuel est nécessaire mais pas suffisant. Vous devez aussi documenter la stratégie de versionnement des schémas, les garanties de compatibilité et l'historique des changements cassants.
Cohérence éventuelle
Les systèmes event-driven sont éventuellement cohérents par nature. Quand le Service A publie un événement, le Service B peut le traiter des millisecondes plus tard ou des minutes plus tard (si le consommateur est en retard ou si des retries sont nécessaires). Le système est dans un état incohérent pendant cette fenêtre.
La documentation devrait capturer ces frontières de cohérence. Quelles parties du système sont fortement cohérentes ? Lesquelles sont éventuellement cohérentes ? Quel est le délai de propagation attendu ? Que se passe-t-il pendant la fenêtre d'incohérence ?
Dead letter queues et gestion des erreurs
Quand un consommateur d'événements échoue à traiter un message, l'événement va typiquement dans une dead letter queue (DLQ). Mais que se passe-t-il ensuite ? Qui surveille la DLQ ? Quelle est la stratégie de retry ? Comment les messages poison sont-ils gérés ?
Ces patterns de gestion d'erreurs sont critiques pour le comportement du système mais sont rarement documentés. Ils font partie de l'architecture, et ils devraient être visibles dans la documentation.
Modéliser les systèmes event-driven avec le C4
Le modèle C4 peut représenter efficacement les architectures event-driven avec quelques adaptations dans la façon dont vous utilisez chaque niveau.
Contexte Système : se concentrer sur les flux de données, pas les appels
Au niveau du Contexte Système, les architectures event-driven et synchrones se ressemblent. Votre système interagit avec des utilisateurs et des systèmes externes. La différence clé est dans la façon dont vous labellisez les relations.
Au lieu de "appelle" ou "interroge", utilisez des labels qui décrivent le flux de données :
- "Envoie des événements de commande vers"
- "Reçoit des confirmations de paiement depuis"
- "Publie des événements analytics vers"
Ces labels suggèrent la nature asynchrone de la communication sans encombrer la vue de haut niveau avec des détails d'implémentation.
Diagramme de Containers : rendre le broker visible
Le diagramme de Containers est là où l'architecture event-driven se distingue. Le message broker (Kafka, RabbitMQ, Amazon SQS/SNS, Google Pub/Sub) devrait être un container de premier plan dans votre diagramme, pas un détail d'implémentation invisible.
Voici comment un diagramme de Containers pour un système e-commerce event-driven pourrait se présenter :
systems:
- name: E-Commerce Platform
type: software_system
containers:
- name: Order Service
type: service
technologies: [Go, PostgreSQL]
- name: Inventory Service
type: service
technologies: [Java, PostgreSQL]
- name: Notification Service
type: service
technologies: [Python, Redis]
- name: Analytics Service
type: service
technologies: [Python, ClickHouse]
- name: Event Bus
type: queue
technologies: [Apache Kafka]
relationships:
- from: Order Service
to: Event Bus
label: "Publie OrderCreated, OrderCancelled"
- from: Event Bus
to: Inventory Service
label: "Délivre les événements de commande"
- from: Event Bus
to: Notification Service
label: "Délivre les événements de commande et de paiement"
- from: Event Bus
to: Analytics Service
label: "Délivre tous les événements de domaine"
- from: Inventory Service
to: Event Bus
label: "Publie InventoryReserved, InventoryReleased"
Remarquez comment l'Event Bus est au centre du diagramme, et les relations nomment explicitement les types d'événements qui y circulent. Cela rend les flux d'événements visibles sans créer de flèches directes entre chaque producteur et chaque consommateur.
Event Channels : un concept de premier plan
Les topics, queues et streams individuels au sein du message broker méritent leur propre documentation. Chaque event channel a des propriétés qui comptent pour comprendre le système :
- Nom du channel : Le nom du topic Kafka, de la queue RabbitMQ ou de la queue SQS
- Types d'événements : Quels événements circulent à travers ce channel
- Producteurs : Quels services publient sur ce channel
- Consommateurs : Quels services consomment depuis ce channel
- Sérialisation : Comment les événements sont encodés (JSON, Avro, Protobuf)
- Stratégie de partitionnement : Comment les événements sont distribués entre les partitions
- Politique de rétention : Combien de temps les événements sont conservés
- Garanties d'ordonnancement : Si l'ordre est préservé et à quelle granularité
Dans Archyl, les event channels sont un type d'entité dédié. Vous créez un event channel, spécifiez ses propriétés, et le liez aux services qui y produisent et en consomment. Cela crée un modèle structuré et interrogeable de vos flux d'événements.
Par exemple, un event channel "orders" pourrait être documenté comme :
- Nom : orders
- Broker : Kafka
- Producteurs : Order Service
- Consommateurs : Inventory Service, Notification Service, Analytics Service, Billing Service
- Types d'événements : OrderCreated, OrderUpdated, OrderCancelled, OrderCompleted
- Sérialisation : Avro avec Schema Registry
- Partitionnement : Par order ID
- Rétention : 7 jours
Ce niveau de détail rend l'infrastructure invisible visible et interrogeable. Quand un développeur a besoin de savoir qui consomme les événements de commande, la réponse est documentée et trouvable.
Diagramme de Components : Event Handlers et Publishers
Au niveau Component, les services event-driven ont des structures internes distinctives qui valent la peine d'être documentées pour les services complexes :
- Event Handlers : Components qui consomment et traitent des types d'événements spécifiques
- Event Publishers : Components qui produisent des événements
- Sagas / Process Managers : Components qui orchestrent des workflows multi-étapes via les événements
- Projections : Components qui construisent des modèles de lecture à partir des flux d'événements
Un diagramme de Components pour le Service de Commandes pourrait inclure :
- Order Controller -- gère les requêtes HTTP pour la gestion des commandes
- Order Processor -- logique métier principale pour la création et validation des commandes
- Event Publisher -- publie OrderCreated, OrderUpdated, OrderCancelled sur Kafka
- Payment Event Handler -- consomme les événements PaymentProcessed et PaymentFailed
- Order Saga -- gère le workflow de fulfillment des commandes à travers les services
Documentez ces components quand le service est assez complexe pour le justifier -- en particulier pour les services qui participent à des patterns de chorégraphie ou d'orchestration.
Documenter les patterns event-driven courants
Certains patterns apparaissent de manière répétée dans les systèmes event-driven. Les documenter explicitement évite aux équipes de devoir rétro-ingénierer les patterns à partir du code.
Event Sourcing
Dans les systèmes event-sourcés, l'état d'une entité est dérivé d'une séquence d'événements plutôt que stocké comme un snapshot. Le flux d'événements est la source de vérité, et l'état actuel est une projection.
Documentez l'event sourcing en :
- Identifiant quelles entités sont event-sourcées
- Listant les types d'événements dans le flux d'événements de chaque entité
- Documentant les projections qui dérivent les modèles de lecture des flux
- Notant la stratégie de snapshotting (le cas échéant)
CQRS (Command Query Responsibility Segregation)
Le CQRS sépare les opérations d'écriture (commands) des opérations de lecture (queries), utilisant souvent des événements pour garder le modèle de lecture synchronisé avec le modèle d'écriture.
Documentez le CQRS en :
- Séparant clairement les containers côté command des containers côté query dans le modèle C4
- Documentant le flux d'événements du côté écriture vers le côté lecture
- Notant le modèle de cohérence (combien le modèle de lecture peut être en retard)
Chorégraphie vs. orchestration
En chorégraphie, les services réagissent aux événements indépendamment. Aucun coordinateur central n'existe. En orchestration, un service central (l'orchestrateur ou saga) coordonne le workflow en envoyant des commands et en écoutant les réponses.
Documentez quel pattern votre système utilise pour chaque workflow. Si vous utilisez la chorégraphie, documentez la séquence attendue d'événements et les services qui participent. Si vous utilisez l'orchestration, documentez la machine à états de la saga et les commands qu'elle émet.
Dead letter queues et patterns de retry
Documentez votre stratégie de gestion d'erreurs pour le traitement des événements :
- Quels événements ont des dead letter queues ?
- Quelle est la politique de retry (nombre, stratégie de backoff) ?
- Qui est responsable de surveiller et retraiter les événements DLQ ?
- Quel alerting est en place pour l'accumulation dans la DLQ ?
Dans Archyl, vous pouvez modéliser les DLQ comme des event channels supplémentaires liés aux channels principaux. Cela rend l'infrastructure de gestion d'erreurs visible dans la documentation d'architecture.
Documenter les schémas d'événements
Les schémas d'événements sont des contrats entre producteurs et consommateurs. Ils méritent le même niveau de documentation que les contrats d'API dans les systèmes synchrones.
Documentation des schémas
Pour chaque type d'événement, documentez :
- Nom de l'événement : Un nom clair et spécifique au domaine (OrderCreated, pas GenericEvent)
- Version du schéma : La version actuelle du schéma
- Champs : Tous les champs avec leurs types, descriptions, et s'ils sont requis ou optionnels
- Payload d'exemple : Un exemple représentatif en JSON/Avro/Protobuf
- Compatibilité : Si le schéma est forward-compatible, backward-compatible ou entièrement compatible
La fonctionnalité de contrat d'API d'Archyl peut être utilisée pour documenter les schémas d'événements aux côtés des spécifications REST et gRPC. Liez le contrat à l'event channel pour créer une connexion directe entre le schéma et l'infrastructure.
Stratégie d'évolution des schémas
Documentez l'approche de votre équipe pour l'évolution des schémas :
- Utilisez-vous un schema registry (Confluent Schema Registry, AWS Glue) ?
- Quel mode de compatibilité est appliqué (backward, forward, full) ?
- Comment les changements cassants sont-ils communiqués aux consommateurs ?
- Quel est le processus de dépréciation des anciennes versions de schéma ?
Ces informations appartiennent à un ADR lié à votre infrastructure d'événements. C'est une décision qui affecte l'ensemble du système et devrait être documentée une fois, clairement, et référencée par toutes les équipes.
Visualiser les flux d'événements
Les diagrammes statiques peuvent montrer l'infrastructure d'événements, mais ils peinent à montrer les flux d'événements -- la séquence d'événements qui implémente un processus métier.
Utiliser les Flows pour les processus métier
La fonctionnalité Flow d'Archyl permet de documenter la séquence d'événements qui implémente un processus métier. Par exemple, un flow "Placement de commande" pourrait montrer :
- Le client soumet une commande via la Web App
- L'API Gateway transmet la requête au Service de Commandes
- Le Service de Commandes valide et persiste la commande
- Le Service de Commandes publie l'événement OrderCreated sur Kafka
- L'Inventory Service consomme OrderCreated, réserve l'inventaire
- L'Inventory Service publie l'événement InventoryReserved
- Le Payment Service consomme InventoryReserved, traite le paiement
- Le Payment Service publie l'événement PaymentProcessed
- Le Notification Service consomme PaymentProcessed, envoie l'email de confirmation
Ce flow montre le comportement de bout en bout qui émerge de l'architecture event-driven. Le code d'aucun service individuel ne révèle ce flow -- il n'existe qu'au niveau architectural.
Utiliser les Overlays pour différentes vues
Créez des overlays pour montrer différents aspects de votre architecture event-driven :
- Overlay de flux d'événements : Met en évidence uniquement les relations liées aux événements, cachant la communication synchrone
- Overlay producteur/consommateur : Code en couleurs les services selon qu'ils produisent, consomment, ou les deux
- Overlay de gestion d'erreurs : Montre les DLQ, les chemins de retry et le monitoring
Les overlays permettent de créer des vues ciblées à partir d'un seul modèle d'architecture, évitant le besoin de multiples diagrammes redondants.
Bonnes pratiques
Nommer les événements d'après des actions du domaine, pas des opérations techniques
Utilisez des noms comme OrderCreated, PaymentFailed, InventoryReserved -- pas DataUpdated, MessageSent ou RecordInserted. Les noms spécifiques au domaine rendent les flux d'événements lisibles au niveau architectural.
Documenter la décision "pourquoi pas synchrone"
Pour chaque interaction event-driven, il y a eu une décision d'utiliser l'asynchrone plutôt que le synchrone. Documentez cette décision. Pourquoi le Service de Commandes publie-t-il un événement au lieu d'appeler directement le Service d'Inventaire ? La réponse (découplage, résilience, scalabilité) devrait être capturée dans un ADR.
Garder la documentation des event channels proche du code
Si vos schémas d'événements sont définis dans le code (fichiers Protobuf, schémas Avro, JSON Schema), liez la documentation d'architecture à ces fichiers. Cela crée une connexion entre la documentation abstraite et l'implémentation concrète.
Revoir les flux d'événements pendant les revues d'architecture
Pendant les revues d'architecture trimestrielles, parcourez vos flux d'événements documentés. Demandez :
- Y a-t-il de nouveaux types d'événements qui ne sont pas documentés ?
- Y a-t-il des types d'événements documentés qui ne sont plus utilisés ?
- De nouveaux consommateurs ont-ils été ajoutés sans mettre à jour la documentation ?
- Les schémas documentés sont-ils encore précis ?
La détection de drift d'Archyl aide à répondre automatiquement à ces questions, mais la revue humaine périodique capte des choses que les vérifications automatisées manquent.
Conclusion
La documentation d'architecture event-driven nécessite un effort intentionnel pour rendre l'invisible visible. Les événements, par conception, découplent les producteurs des consommateurs. C'est une force architecturale mais un défi de documentation.
Le modèle C4 fournit le framework : le Contexte Système pour la vue d'ensemble, les diagrammes de Containers avec le message broker comme élément de premier plan, les event channels pour la documentation détaillée des topics et queues, et les diagrammes de Components pour les event handlers et sagas complexes.
Archyl fournit l'outillage : les event channels comme entités de premier plan, les flows pour documenter les processus métier event-driven, les contrats d'API pour les schémas d'événements, les overlays pour les vues ciblées, et la détection de drift pour capter les changements non documentés.
Documentez votre architecture event-driven de la même façon que vous la concevez : avec intention, structure, et la compréhension que le comportement du système émerge des interactions entre les services, pas d'un seul service isolé.
Démarrez avec Archyl et rendez votre architecture event-driven visible, documentée et comprise.