Table of Contents
Les architectures basées sur les événements dépendent du flux fiable et cohérent de données entre les producteurs et les consommateurs. Au fur et à mesure que les systèmes évoluent, la structure des données d'événements – son schéma – change inévitablement. De nouveaux champs sont ajoutés, les anciens champs sont dépréciés, et parfois des modèles de données entiers changent. Sans stratégie délibérée de gestion de ces changements, les systèmes axés sur les événements peuvent devenir fragiles, déclenchant des erreurs de désérialisation, la perte de données ou une fausse représentation silencieuse de l'information.
Comprendre la version des événements
La mise en forme d'événements est la pratique consistant à identifier et à suivre des versions distinctes d'un schéma d'événements de façon à ce que les producteurs et les consommateurs puissent coexister à différents stades de l'évolution. L'objectif principal est de veiller à ce que les événements puissent être interprétés correctement, peu importe le moment où ils ont été produits ou par quelle version d'un producteur.
La mise en œuvre de la version peut se faire à différents niveaux :
- Version de schéma[ – La définition du schéma lui-même comporte un identifiant de version (p. ex. ). C'est l'approche la plus explicite et fonctionne bien avec les registres de schéma.
- La version de la charge utile – La charge utile d'événement comprend un champ de version (p. ex. ) qui indique au consommateur quel schéma utiliser pour la désérialisation.
- Métadonnées de version[ – Les informations de version sont stockées dans des en-têtes de message ou des métadonnées d'enveloppe, séparés de la charge utile.
Chaque approche a des compromis. La version de schéma centralise la gestion des schémas et facilite les vérifications de compatibilité, mais elle nécessite souvent des recherches de registre de schéma d'exécution. La version de charge utile est simple à implémenter et fonctionne dans des systèmes sans registre, mais elle peut gonfler la charge utile et nécessite une manipulation soigneuse des champs de version. La version de métadonnées maintient le schéma de charge utile propre, mais ajoute de la complexité à la logique d'analyse initiale du consommateur.
Stratégies pour Schema Evolution
L'évolution du schéma est l'ensemble de règles et de pratiques qui régissent la façon dont les schémas changent au fil du temps tout en préservant la compatibilité.
Validation du schéma
Utilisez un langage de définition formel du schéma et un outil de validation pour appliquer les règles de structure des données.Les choix les plus populaires sont JSON Schema[, Apache Avro[ et Protocol Buffers (Protobuf).Ces langages fournissent des mécanismes intégrés pour l'évolution, tels que les valeurs par défaut, les champs optionnels et les modes de compatibilité. La validation garantit que chaque événement produit répond à la structure attendue, réduisant ainsi les risques de corruption silencieuse des données en aval.
Compatibilité avec les systèmes de retenue
Un changement de schéma est compatible avec le rétro-utilisateur si un consommateur écrit pour le nouveau schéma peut encore lire des événements produits par l'ancien schéma. Les techniques les plus courantes sont les suivantes:
- Ajouter des champs optionnels – Les nouveaux champs doivent être facultatifs avec des valeurs par défaut raisonnables (p. ex. ou une valeur zéro). Les anciens événements omettent simplement ces champs et le consommateur utilise la valeur par défaut.
- Ajouter de nouvelles valeurs enum[ – De nouvelles valeurs enum peuvent être ajoutées tant qu'elles ne brisent pas la logique existante.
- Faire des champs nuls[ – Changer un champ obligatoire en option est compatible avec l'arrière; l'inverse est un changement de rupture.
- Utilisation de promotions de type[ – Élargissement d'un champ (p. ex., → , → ) est souvent sûr, mais le rétrécissement peut causer une perte de données.
Compatibilité avec l'avenir
La compatibilité avec l'avenir permet à un consommateur plus âgé de lire les événements produits par un producteur plus récent.
- Lecteurs tolérants – Les consommateurs devraient ignorer les champs inconnus pendant la désérialisation. La plupart des formats de schéma supportent ceci: Avro=s option, Protobuf=s et conservation de champ inconnu, et JSON Schema=s .
- Valeurs par défaut pour les nouveaux champs – Les producteurs peuvent remplir de nouveaux champs avec des valeurs par défaut lorsque le consommateur ne peut pas les utiliser, mais c'est vraiment une préoccupation de compatibilité en arrière.
- Éviter les changements structurels – Les champs de renaissement, les types de changement ou la réorganisation des structures imbriquées brisent généralement la compatibilité vers l'avant.
Version dans les métadonnées
Un schéma commun est d'utiliser un en-tête dans les en-têtes d'Apache Kafka ou un champ dans un objet d'enveloppe. Cette approche permet aux producteurs et aux consommateurs de gérer la résolution du schéma à la couche d'application sans modifier le schéma de charge utile lui-même. Cependant, il incombe au consommateur de récupérer la version du schéma correcte avant la désérialisation, en utilisant généralement un registre de schéma.
Registres de schéma
Un registre de schéma est un service centralisé qui stocke et valide les schémas sur plusieurs versions. Il applique les règles de compatibilité (p. ex., rétrograde, avant, plein, ou aucun) et fournit un moyen pour les consommateurs de récupérer le schéma nécessaire pour désérialiser un événement. Le registre de schéma de confluent est le plus utilisé pour les systèmes basés sur Kafka, mais il existe des solutions de rechange open-source comme le registre Apiquio et le registre de schéma d'Azure. L'utilisation d'un registre permet d'automatiser les vérifications de compatibilité dans les pipelines CI/CD et empêche le déploiement de schémas incompatibles à la production.
Mise en œuvre de la version dans la pratique
Passer de la théorie à la mise en oeuvre exige de faire des choix concrets sur les formats de sérialisation, l'outillage et les processus.
Choisir un format de sérialisation
Le format de sérialisation détermine comment les schémas sont définis, comment ils évoluent et quelle compatibilité garantit que vous obtenez. Voici une comparaison des trois options principales:
- Apache Avro – Conçu pour l'évolution du schéma. Prend en charge les modes de compatibilité vers l'arrière, vers l'avant et vers l'ensemble. Utilise un format binaire compact avec forte typage. Bien intégré avec le registre du schéma confluent.
- Protocol Buffers (Protobuf) – supporte également l'évolution via les numéros de champ et les champs optionnels. Plus efficace qu'Avro pour certaines charges de travail. Fonctionne bien dans les systèmes polyglottes avec gRPC. Les règles de compatibilité sont moins intégrées mais peuvent être appliquées avec des outils tiers comme Buf.
- JSON Schema – L'homme est lisible, largement pris en charge et facile à déboguer. Pas de sérialisation binaire intégrée; généralement utilisée avec JSON. Evolution est gérée par l'intermédiaire des spécifications (p. ex. ], ).
Dans de nombreuses organisations, le choix est déjà limité par l'infrastructure existante. Si vous commencez à peine, Avro offre la chaîne d'outils d'évolution de schéma la plus mature pour le streaming d'événements, tandis que Protobuf est un concurrent fort pour la communication de microservices.
Maintien de la compatibilité des matrices
Une matrice de compatibilité map des versions de schéma producteur vers les versions de schéma consommateur, mettant en évidence toute incompatibilité connue. Cette matrice peut être maintenue comme un fichier YAML dans votre dépôt de schéma ou générée automatiquement par un registre de schéma. Il sert à la fois d'outil de communication pour les équipes et de source de vérité pour les tests automatisés.
Par exemple, une matrice pourrait enregistrer que est compatible avec mais non compatible avec l'avant, ce qui signifie que les anciens consommateurs se briseront s'ils reçoivent des événements v2. Cela oblige à un déploiement coordonné : soit tous les consommateurs sont mis à niveau avant que n'importe quel producteur publie v2, soit le producteur continue d'envoyer des événements v1 jusqu'à ce que la flotte de consommateurs soit prête.
Essai de compatibilité automatique
Les contrôles manuels de la compatibilité des schémas deviennent rapidement inexploitables. Intégrez la validation des schémas et les contrôles de compatibilité dans votre pipeline CI/CD. Chaque fois qu'un producteur change de schéma, le pipeline doit :
- Enregistrez le nouveau schéma dans le registre des schémas avec un mode de compatibilité spécifié.
- Si l'enregistrement échoue, avorter la compilation et exiger de l'équipe de fixer le schéma (ou de bloquer explicitement la version de l'événement).
- Exécuter des tests d'intégration avec les consommateurs réels en exerçant le nouveau schéma pour attraper les problèmes d'exécution.
- Si vous réussissez, publiez la nouvelle version du schéma avec une entrée de journal de changement.
Des outils comme Confluents Les plugins Maven ou custom shell scripts[ (et maintenant GitHub Actions) peuvent automatiser cette option. Pour Protobuf, la commande Buf CLI fournit une commande robuste qui impose des règles de compatibilité.
Communication et documentation
Les changements de schéma sont des contrats d'API implicites. Ils doivent être communiqués comme tout autre changement d'API. Conservez un journal de changement pour chaque type d'événement, en notant ce qui a changé, pourquoi et quelles garanties de compatibilité s'appliquent. Utilisez un outil de documentation de schéma (par exemple Backstage, un site généré à partir de votre registre de schéma) afin que les équipes puissent parcourir les schémas disponibles et leur historique.
Gestion des changements de rupture
Malgré tous les efforts pour les éviter, il faut parfois rompre les changements (p. ex., renommer un champ, changer un type de données, restructurer des objets imbriqués).
- Traitements modifiés – Produire des événements sur un nouveau sujet (p. ex. ) tandis que les anciens consommateurs continuent à lire à partir de l'ancien sujet.
- Processus de rétractation – Gardez le même sujet mais augmentez le numéro de version majeur de l'événement. Les consommateurs doivent vérifier la version et décider comment désélaborer.
- Dual écrit – Pendant une période de transition, le producteur émet les formats anciens et nouveaux. Ceci est souvent utilisé comme tremplin pendant que les consommateurs sont migrés. Il double le trafic et augmente la complexité, donc il devrait être temporaire.
Quel que soit le chemin que vous choisissez, jumelez toujours le changement de rupture avec une politique de déprécation claire et un déploiement surveillé.
Considérations avancées
Lorsque la version d'événement et l'évolution du schéma se croisent avec l'approvisionnement en événement, les environnements polyglottes ou les magasins spécialisés d'événements, des nuances supplémentaires se présentent.
Sourcing événementiel et schéma évolution
Dans les systèmes d'événements, les événements sont la source de la vérité et ne sont jamais supprimés ou modifiés. L'évolution du schéma devient une préoccupation critique de conception parce que chaque événement passé doit rester interprétable pour toujours. La pratique recommandée est de stocker les événements dans un format qui supporte l'évolution du schéma nativement (par exemple, Avro ou Protobuf avec un registre de schéma) et d'ajouter toujours des champs avec des défauts plutôt que de modifier ceux existants.
Version dans les environnements polyglottes
Lorsque les producteurs et les consommateurs sont écrits dans différentes langues, vous devez vous assurer que le format de sérialisation et la définition du schéma sont cohérents entre les langues. Avro et Protobuf ont tous deux une génération de code robuste pour de nombreuses langues, mais chaque langue peut gérer des champs inconnus ou des valeurs par défaut légèrement différemment. Testez la compatibilité cross-language au début du développement. Utilisez un registre de schéma qui fournit des sérialisateurs langagiers (p. ex. Confluent=S REST Proxy for Avro) pour éviter la duplication de la logique de résolution du schéma.
Versionnement avec les magasins d'événements
Les systèmes comme EventStoreDB ou Apache Kafka (utilisés comme magasin d'événements) ont souvent leurs propres mécanismes de gestion de schéma. EventStoreDB prend en charge les types d'événements et les projections, mais l'évolution de schéma reste votre responsabilité. Avec Kafka, le registre de schéma est l'outil principal. Cependant, lorsque vous utilisez Kafka comme magasin d'événements à long terme, envisagez d'ajouter une politique de conservation qui compacte ou supprime les anciens événements seulement après que tous les consommateurs aient été migrés vers un nouveau schéma. Sinon, vous risquez d'avoir des événements avec un schéma obsolète que aucun consommateur ne peut lire.
Conclusion
En adoptant des registres de schémas, en choisissant le bon format de sérialisation et en automatisant les vérifications de compatibilité, les équipes peuvent évoluer leurs schémas de données en toute confiance. La compatibilité vers l'arrière et vers l'avant protège les consommateurs contre les défaillances inattendues, tout en conservant des politiques claires de communication et de déprécation. Les systèmes les plus résistants traitent les changements de schéma comme des changements de première classe de l'API, en planifiant pour eux dès le premier jour. Investir dans ces pratiques est rentable à chaque mise à jour d'un service, un nouveau consommateur est ajouté ou un événement historique est rejoué, en veillant à ce que vos flux d'événements demeurent une base fiable pour votre architecture.