Je fais un projet de recherche où je recherche les options pour gérer les changements dans une architecture de microservice événementielle.
Donc, disons que nous avons obtenu une application où nous avons obtenu quatre services différents. Chacun de ces services possède sa propre base de données pour stocker les données locales.
Dans cette configuration, les quatre services communiquent entre eux à l'aide d'un bus d'événements. Ainsi, lorsqu'un événement se produit dans un service, il publie un événement. Tous les autres services intéressés par cet événement le traiteront à leur manière.
Dans ce cas, les différents services de l'architecture doivent avoir des «contrats» sur le contenu de ces événements (attributs, etc.). Les services ont donc des "dépendances faiblement couplées" à ces événements
Ma question est: comment gérer les changements dans ces événements?
Supposons donc que le service A enregistre de nouveaux utilisateurs dans l'application. Il envoie donc un événement "" UserRegistered ". Le service B récupère cet événement et le traite. Mais certains développeurs de l'équipe du service C ont décidé qu'ils avaient également besoin du sexe d'un utilisateur enregistré. L'événement est donc modifié et l'attribut gender est ajouté à l'événement "UserRegistered".
Comment pouvons-nous nous assurer que le service B peut toujours récupérer le même événement avec cet attribut supplémentaire sans redéployer?
Et y a-t-il d'autres façons d'aborder ce problème que de versionner ces événements?
Réponses:
Les événements ne concernent pas ce qui a changé. Ils concernent le moment où quelque chose a changé.
Je peux créer un système d'événements complètement découplé du contenu qui a changé. De cette façon, tout ce que j'apprends d'un événement, c'est qu'un objet a été mis à jour. Si je me soucie même que l'objet ait été mis à jour, je dirai alors à tout ce qui sait comment parler à cet objet pour lui demander ce qui a changé.
Cela ne résout pas le problème de la communication de ces changements. Cela l'empêche simplement de faire partie du système d'événements.
Un exemple d'une façon de résoudre le problème des différentes versions de données est de faire en sorte que l'observateur crée et remette à l'objet observé une collection. L'objet observé remplit la collection avec ses dernières données et lorsque le contrôle revient, vous (l'observateur) avez ce dont vous avez besoin. S'il y a un supplément dont vous ne vous souciez pas, parce que vous n'en avez jamais entendu parler, vous l'ignorez simplement.
De nombreuses autres façons d'écorcher ce chat, mais c'est celle que j'ai fait fonctionner exactement dans ce cas.
la source
UserRegistered
événement, s'il y avait un événement qui ne contenait pas d'informations sur l'utilisateur, il y aurait 1 message publié sur le bus, puis {nombre de services intéressés} demandes au service utilisateur ou messages publiés au bus. Ensuite, il y aurait {nombre de services intéressés} des messages de différentes tailles. Bien que je pense que c'est probablement une conception plus propre sur papier, si les performances sont un problème, elles se décomposent dans tout système non trivial, en particulier sur un réseau.Des frameworks comme NServiceBus gèrent cela en utilisant la gestion des événements avec la distribution polymorphe des messages.
Par exemple, la version 1 du service A peut publier un événement en tant que IUserRegistered_v1. Lorsque Service A version 1.1 doit inclure un champ supplémentaire, il peut déclarer l'interface IUserRegistered_v1_1, qui hériterait de IUserRegistered_v1 ainsi que déclarer certains champs supplémentaires.
Lorsque le service A publie un événement IUserRegistered_v1_1, NServiceBus enverra le message à tous les points de terminaison qui gèrent IUserRegistered_v1 ou IUserRegistered_v1_1.
la source
Amélioration incrémentale
Une modification simple du modèle est que lorsque les auditeurs s'inscrivent en tant qu'observateurs, ils incluent une liste ou une autre structure des éléments de données qu'ils souhaitent connaître. Cela peut fonctionner si les données renvoyées par le service sont simples, mais si vous avez une bonne quantité de données hiérarchiques, cela peut devenir très compliqué à mettre en œuvre.
Solide comme le roc
Si vous voulez vraiment un moyen robuste de faire cette conception, le service de telle sorte qu'il conserve un historique des modifications qui ont été apportées aux données qu'il stocke. Essentiellement, vous ne mettez jamais à jour les enregistrements de votre base de données, vous ajoutez de nouveaux enregistrements où chacun représente le changement. Chacun de ces nouveaux enregistrements est associé à un identifiant d'événement qui identifie l'action. Un enregistrement pair est stocké avec toutes les informations pertinentes sur le changement (qui, quoi, quand, etc.). Cela présente d'autres avantages qui sortent du cadre de cette réponse mais qui sont abordés dans cet article sur le théorème CAP .
Lorsqu'une modification est effectuée, vous créez l'enregistrement d'événement et ajoutez toutes les nouvelles données à votre base de données. Ensuite, vous publiez un événement pour les écouteurs qui contient (au minimum) l'ID d'événement. Les écouteurs peuvent alors demander les données associées à cet identifiant et obtenir la version des données qui lui sont associées. Chaque auditeur est alors en mesure d'obtenir tout ce dont il a besoin sans coupler les besoins d'autres auditeurs différents. Je vous conseille d'ajouter un sous-ensemble des champs de données les plus couramment utilisés au message d'événement afin que les écouteurs puissent filtrer les événements qui ne les intéressent pas. Cela peut réduire le bavardage du processus et certains écouteurs n'auront peut-être jamais besoin d'appeler de retour du tout. Cela vous protège également des problèmes de synchronisation. Si vous rappelez simplement le service et obtenez les données en fonction de la clé, il peut y avoir d'autres changements qui se sont produits entre l'obtention de l'événement et la récupération des données pour celui-ci. Cela peut ne pas avoir d'importance pour tous les auditeurs, mais cela peut créer de gros problèmes si vous avez besoin de connaître tous les changements. L'amélioration incrémentielle de la conception ci-dessus est compatible avec cette approche si vous voulez vraiment la mettre à 11.
Une partie de cela peut être exagérée pour ce que vous devez faire, mais d'après mon expérience, si vous ne disposez pas d'un moyen précis de voir comment un enregistrement évolue au fil du temps, vous ou une personne travaillant avec vos données le voudrez éventuellement.
la source
@CandiedOrange fait un point valable dans un commentaire à sa propre réponse concernant les formats de données extensibles comme xml.
Cela ne devrait pas avoir d'importance tant que vous ajoutez des données. Cependant, fournissez des valeurs par défaut raisonnables pour les événements plus anciens / les champs non obligatoires.
Vous ne devriez avoir qu'à mettre à jour les services qui se soucient - dans ce cas - du genre. Un analyseur xml / json doit pouvoir ignorer les données supplémentaires pour les autres services. Cela dépend bien sûr de votre choix de parseur et de format de données d'événement.
Cependant, je ne suis pas d'accord avec les événements ne disposant pas des données pertinentes. Pour la recherche d'événements, les événements doivent définir ce qui a changé. Lors de la réception d'un événement, les autres services ne devraient pas avoir à récupérer les données de la source de l'événement.
la source