Documentation de l'architecture event-driven avec le modèle C4 - Archyl Blog

Les architectures event-driven sont puissantes mais notoirement difficiles à documenter. Les événements sont invisibles, asynchrones et découplés par conception. Ce guide montre comment utiliser le modèle C4 pour documenter les flux d'événements, les event channels et les patterns asynchrones -- et comment Archyl rend les systèmes event-driven visibles.

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 :

  1. Le client soumet une commande via la Web App
  2. L'API Gateway transmet la requête au Service de Commandes
  3. Le Service de Commandes valide et persiste la commande
  4. Le Service de Commandes publie l'événement OrderCreated sur Kafka
  5. L'Inventory Service consomme OrderCreated, réserve l'inventaire
  6. L'Inventory Service publie l'événement InventoryReserved
  7. Le Payment Service consomme InventoryReserved, traite le paiement
  8. Le Payment Service publie l'événement PaymentProcessed
  9. 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.