Gérer les changements dans une architecture de microservice pilotée par les événements


9

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?


Quel format sont vos messages, ou est-ce quelque chose que vous pouvez concevoir? Certains formats de message permettent des attributs facultatifs. Selon l'implémentation du lecteur, vous pouvez ajouter des attributs facultatifs sans avoir à mettre à jour tous les lecteurs.
Thomas Owens

Je suis libre de choisir un format à utiliser pour mes messages. Je pense que l'utilisation de JSON est la meilleure solution. Il est important que ces différents services soient créés dans différentes langues. C'est pourquoi un format général comme XML ou JSON est nécessaire.
CGeense

Réponses:


1

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.


Cela n'augmenterait-il pas considérablement le trafic entre les services? En utilisant l'exemple de la question, un 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.
Thomas Owens

@ThomasOwens L'envoi de données avec l'événement signifie que si j'ai N observateurs j'envoie N messages. L'envoi de l'événement seul signifie que j'envoie des messages 3N dont seulement 1 contient le paquet de données. Cela évolue très bien même sur un réseau. Le seul inconvénient important est qu'il triple votre retard. Cela ne veut pas dire que vous ne pouvez pas trouver une solution plus optimale pour une situation particulière. Je démontre que les systèmes d'événements et les versions de données ne doivent pas être couplés.
candied_orange

1
L'idée de ce bus événement est de découpler les différents services. En utilisant un middleware, nous pouvons nous assurer que ces services ne se connaissent pas et peuvent exister et communiquer sans se connaître. Si nous supprimons l'état de ces événements et laissons les services se connecter directement, nous couplons ces services. De cette façon, nous ne pouvons jamais redéployer un seul service sans avoir à redéployer le reste
CGeense

1
Le point ici est que le système d'événements ou non, vous avez besoin de données extensibles. JSON ou XML font très bien si vous ne changez pas les noms ou les structures qui ont été précédemment établies. J'ai fait de même avec les collections. Le système d'événements ne devrait pas se soucier des sexes. S'il envoie des données, il devrait simplement les transmettre et quelque chose à l'autre bout se souciera des sexes ou non.
candied_orange

1

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.


0

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.


-1

@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.


Mon point est qu'il doit gérer toutes sortes de changements. Pensez à un service qui diffuse un événement. Et cet événement contient une propriété qui est obsolète et doit être supprimée. Même si ces autres services n'utilisent pas la propriété, cela les cassera simplement parce qu'ils s'y attendent. J'ai donc lu cet article sur martinfowler.com sur les contrats axés sur les consommateurs: martinfowler.com/articles/consumerDrivenContracts.html Lors de l'application de ce principe. Chaque prestataire (événement) sait ce qu'on attend de lui. avec cette information, il peut valider s'il casse des consommateurs.
CGeense
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.