Associations plusieurs à plusieurs dans les microservices

13

J'ai actuellement deux microservices. Nous les appellerons Aet B.

La base de données sous microservice Aa le tableau suivant:

A
|-- users

La base de données sous microservice Ba le tableau suivant:

B
|-- trackers

Les exigences le stipulent userset trackersont une relation plusieurs-à-plusieurs.

Je ne sais pas comment gérer correctement cela dans une architecture de microservices.

Je pouvais voir cela fonctionner de trois manières:

  1. Une user_trackerstable est ajoutée au microservice A. Cela agit de manière similaire à une table de jointure contenant des "clés étrangères" vers userset trackers.
  2. Une ownerstable est ajoutée au microservice B. Cette table agit de manière similaire à une table de jointure polymorphe. Cela permettrait à n'importe quel service de créer une association avec un tracker. Cela peut ressembler à ceci: B |-- trackers |-- owners |-- owner_id |-- owner_type |-- tracker_id
  3. Gardez des enregistrements pour userset trackersdans chaque microservice. Gardez-les synchronisés avec une sorte de système de pubsub.

J'allais à l'origine choisir l'option 2 parce que j'aimais le fait qu'elle préservait les limites des transactions. Je peux créer un tracker et l'associer à quelque chose atomiquement. Cependant, il semble hors de portée du microservice B. Pourquoi le microservice devrait-il Bveiller à ce que le microservice Aveuille créer une association?

J'ai l'impression qu'il y a probablement ici un bon schéma que je ne connais pas. Est-ce que l'une des options que j'ai présentées est logique? Y a-t-il une autre option qui pourrait avoir plus de sens?

anthonateur
la source

Réponses:

12

Tout d'abord, je commencerais par la description du domaine. Vous n'avez pas mentionné de quoi il s'agit (je suppose, mais ce ne serait qu'une supposition). Après cela, j'essayerais de le décomposer en utilisant une analyse de la chaîne de valeur ou une cartographie des capacités commerciales . Et seulement après cela, je penserais à la mise en œuvre.

Compte tenu de votre problème, la première chose qui me vient à l'esprit est que vous avez mal identifié les limites de vos services, simplement parce qu'ils ont besoin les uns des autres. Vous ne voulez pas vous retrouver avec un monolithe distribué , n'est-ce pas ?

La deuxième chose est que vous n'avez probablement pas assez bien travaillé sur votre domaine. Quel concept est représenté avec la userstable? Est-ce un registered user, avec toutes les informations et comportements requis pour l'inscription? Êtes-vous sûr que c'est le bon concept pour communiquer avec trackers(quoi que ce soit)? Donc, si je comprends bien, votre option 2 est exactement à ce sujet: introduire le ownerconcept qui est beaucoup plus proche de votre domaine. Si c'est vraiment le cas, je suis également pour l'option 2.

Cependant, cela semble hors de portée pour le microservice B. Pourquoi le microservice B devrait-il veiller à ce que le microservice A veuille créer une association?

Il s'agit de frontières. Je suppose que vous voulez former des microservices autour d'entités. C'est là que SOA a échoué avec son architecture de service en couches . La meilleure approche consiste à créer des services qui représentent une fonction métier, afin qu'ils encapsulent à la fois les données et le comportement. D'un point de vue plus pratique, il s'agit de créer des services autour de processus métier ou de cas d'utilisation. Par exemple, vous pourriez avoir un service pour l'enregistrement des utilisateurs. Il contient les données de l'utilisateur et le comportement requis pour enregistrer un utilisateur. Ainsi, le concept de userse forme naturellement et n'appartient qu'au service A. Et cela m'amène au point suivant: l'autre façon de penser les services est le contexte borné . C'est une bonne pratique pour aligner les services et les contextes délimités.

Lorsque l'utilisateur est enregistré, l' UserCreatedévénement peut être émis. Je suppose que votre deuxième service l'intéresse. Ainsi, en le recevant, une entité complètement différente pourrait être créée, disons, une Ownerentité (quelle qu'elle soit non plus). Je suis presque sûr qu'il y a beaucoup de collaborations intéressantes entre elle et l' trackerentité - gardez-les dans un seul service.

Soyez extrêmement prudent avec l'option 3. Si vous copiez des données, la fonctionnalité suit. Il en résulte un couplage serré. Et ne couvrez pas avec le terme CQRS , il ne s'agit pas de synchronisation de données entre services via des événements.

Zapadlo
la source
J'adore le terme «monolithe distribué», mais la façon dont il est défini dans le lien que vous donnez ne semble pas être directement liée à la question ici. La façon dont je pense que vous l'utilisez est liée au couplage entre les services et l'article se concentre sur les dépendances binaires. Je pense que la façon dont vous utilisez est supérieure, mais j'ai du mal à trouver une référence qui la définit clairement de cette façon.
JimmyJames
J'ai toujours inclus des services de bavardage dans la catégorie "monolithes distribués", qui n'est pas très répandue et courante.
Zapadlo du
6

La réponse de Zapadlo contient beaucoup de bonnes informations et un bon raisonnement. Je vais ajouter ici un petit conseil pratique qui peut faciliter le traitement de vos problèmes et les conseils dans cette réponse.

La façon dont vous avez formulé votre question de conception concerne les structures de base de données et la manière de répondre à une nouvelle exigence pour vos structures. Cela implique que vous construisez la conception du service à partir de votre modèle de données. Par exemple, ce que je ne vois pas, c'est comment la relation entre les utilisateurs et les trackers doit être accessible ou utilisée.

Dans la conception de services, la structure de l'interface est l'élément le plus important de la conception. En fait, la mise en œuvre est presque hors de propos en comparaison notamment dans le cas des microservices. La raison en est qu'une fois que vous avez mis votre service en place, toutes les dépendances de votre service devraient exister uniquement sur l'interface. Si vous réussissez, vous devriez être en mesure de réécrire complètement l'implémentation sans aucun consommateur. Et c'est le principal avantage de l'autonomie. Personne ne se soucie de la façon dont vous l'avez construit. Ils en ont juste besoin pour fonctionner comme vous l'avez annoncé.

Avant que quiconque puisse déterminer à quoi cela ressemble dans la base de données ou où vous le souhaitez, vous devez vraiment expliquer comment ces informations vont être utilisées. Est-ce quelque chose qui sera exposé via un service ou s'agit-il d'une sorte de données que vous souhaitez mélanger pour l'analyse?

D'un autre côté, j'éviterais les dépendances bidirectionnelles à presque tous les prix. Si vous avez des dépendances, vous voulez vraiment qu'un seul côté connaisse l'autre. Une fois les dépendances dans les deux sens, leurs services deviennent essentiellement une unité atomique.

JimmyJames
la source
0

Cela dépend en grande partie du domaine lui-même. Si un utilisateur avec zéro trackers n'a pas de sens, le service utilisateur doit connaître les trackers. Si un tracker doit avoir un utilisateur, les trackers doivent connaître les utilisateurs. Si quelque chose comme avoir un tracker avec plusieurs propriétaires ou pouvoir transférer un tracker d'un utilisateur à un autre a du sens, alors peut-être que ces informations appartiennent à un autre service.

Signe
la source
0

Question: Pourquoi vos données sont-elles séparées le long des tables de données?

J'aurais tendance à choisir l'option 3: les services sont totalement séparés et peuvent répondre aux questions respectives auxquelles ils pourraient avoir besoin de répondre. De plus, ils sont beaucoup plus résistants. Mais attention, vos services pourraient se désynchroniser s'ils manquent des événements, mais cela peut être résolu grâce à une cohérence éventuelle.

En outre, vous pourriez envisager de fusionner les deux services - si les deux ne sont pas en mesure de répondre sans se connaître, je les fusionnerais simplement car ils font probablement partie d'un seul domaine.

Christian Sauer
la source
Cela fait partie de la religion des microservices, que chaque service a besoin d'une autonomie complète. Thomas Erl le décrit comme l'un des principes de l'orientation des services dans "Principe of Service Design" c. 2008.
JimmyJames
@JimmyJames En tant que personne qui écrit moi-même une architecture ms: Il y a beaucoup de débats sur la question de la taille d'un ms. Dans ce cas, la taille peut même ne pas avoir d'importance car les services peuvent ne pas être séparés correctement - par exemple, ne coupez pas le long des tables, coupez le long des domaines commerciaux.
Christian Sauer
Droite. Le problème est qu'il existe actuellement un culte majeur du fret autour des microservices. Je vois beaucoup de gens mettre en œuvre des microservices parce que c'est ce que font les enfants sympas et ne considèrent pas ou ne comprennent pas les compromis. Par exemple, j'ai l'impression que beaucoup de gens pensent que l'autonomie de la SEP est une question de technologie et de «cloud». Je le vois plus comme une solution à un problème d'organisation. Le déréférencement du pointeur de négociation pour les E / S réseau est extrêmement coûteux. Vous ne pouvez pas simplement appliquer cela sans réfléchir et vous attendre à ce que tout se passe bien.
JimmyJames
@JimmyJames Je pense que cela peut aussi concerner la technologie - en particulier lorsque les technologies certian sont bien adaptées à certains domaines, mais pas à d'autres. Nous utilisons C # et Python pour nos MS. Une partie de cela est due à des problèmes d'organisation ("J'ai programmé c # pendant 20 ans, je n'ai pas besoin d'apprendre des langages non typés!"). - mais aussi en raison de la nature de notre système. Les parties de science des données sont mieux faites en python, tandis que certaines tâches d'infrastructure et Web sont mieux faites en C #.
Christian Sauer
Bien sûr, c'est une raison assez valable pour le faire. Le problème que je vois est que les gens voudront diviser chaque service en un nœud séparé simplement parce que "nous faisons des microservices" même si tout est écrit avec le même code sur la même plate-forme et qu'il y a une tonne de dépendances entre les services. Les microservices ne présentent vraiment pas beaucoup d'avantages dans ce cas et vous avez ajouté toute une série de nouveaux problèmes.
JimmyJames