28 votes

Partage des données entre les microservices

Architecture actuelle :

enter image description here

Problème :

Nous avons un flux en deux étapes entre les couches frontale et dorsale.

  • Première étape : Le frontend valide une entrée I1 de l'utilisateur sur le microservice 1 (MS1)
  • Deuxième étape : Le frontend soumet I1 et plus d'informations au microservice 2

Le micro service 2 (MS2) a besoin de valider l'intégrité de I1 car il provient du frontend. Comment faire pour éviter une nouvelle requête à MS1 ? Quelle est la meilleure approche ?

Flux que j'essaie d'optimiser en supprimant les étapes 1.3 et 2.3

Flux 1 :

  • 1.1 L'utilisateur X demande des données (MS2_Data) à MS2
  • 1.2 L'utilisateur X persiste les données (MS2_Data + MS1_Data) sur MS1
  • 1.3 Le MS1 vérifie l'intégrité des MS2_Data à l'aide d'une requête HTTP B2B.
  • 1.4 Le MS1 utilise MS2_Data et MS1_Data pour conserver la base de données 1 et construire la réponse HTTP.

Flux 2 :

  • 2.1 L'utilisateur X a déjà des données (MS2_Data) stockées dans la mémoire locale/session.
  • 2.2 L'Utilisateur X persiste les données (MS2_Data + MS1_Data) sur MS1
  • 2.3 Le MS1 vérifie l'intégrité des MS2_Data à l'aide d'une requête HTTP B2B.
  • 2.4 Le MS1 utilise MS2_Data et MS1_Data pour conserver la base de données 1 et construire la réponse HTTP.

Approche

Une approche possible est d'utiliser une requête HTTP B2B entre MS2 et MS1 mais nous dupliquerions la validation dans la première étape. Une autre approche consisterait à dupliquer les données de MS1 à MS2, mais cette solution est prohibitive en raison de la quantité de données et de leur nature volatile. La duplication ne semble pas être une option viable.

Une solution plus appropriée, à mon avis, serait que le frontend ait la responsabilité d'aller chercher toutes les informations requises par le micro service 1 sur le micro service 2 et de les fournir au micro service 2. Cela évitera toutes ces requêtes HTTP B2B.

Le problème est de savoir comment le microservice 1 peut faire confiance aux informations envoyées par le frontend. Peut-être qu'en utilisant JWT pour signer d'une manière ou d'une autre les données du microservice 1 et le microservice 2 sera en mesure de vérifier le message.

Note Chaque fois que le microservice 2 a besoin d'informations de la part du microservice 1, une demande http B2B est effectuée. (La requête HTTP utilise ETAG et Contrôle du cache : max-age ). Comment éviter cela ?

Objectif de l'architecture

enter image description here

Le micro-service 1 a besoin des données du micro-service 2 à la demande pour pouvoir faire persister les données MS1_Data et MS2_Data dans la base de données MS1. L'approche ASYNC utilisant un courtier ne s'applique donc pas ici.

Ma question est de savoir s'il existe un modèle de conception, une meilleure pratique ou un cadre pour permettre ce type de communication.

L'inconvénient de l'architecture actuelle est le nombre de requêtes HTTP B2B qui sont effectuées entre chaque microservice. Même si j'utilise un mécanisme de contrôle du cache, le temps de réponse de chaque micro-service sera affecté. Le temps de réponse de chaque micro-service est critique. L'objectif ici est d'archiver une meilleure performance et d'utiliser le frontend comme une passerelle pour distribuer les données à travers plusieurs micro-services mais en utilisant un mécanisme de contrôle de cache. communication de poussée .

MS2_Data est juste un SID d'entité comme le SID du produit ou le SID du fournisseur que le MS1 doit utiliser pour maintenir l'intégrité des données.

Solution possible

enter image description here

L'idée est d'utiliser la passerelle comme une passerelle api de traitement des demandes qui mettra en cache certaines réponses HTTP de MS1 et MS2 et les utilisera comme réponse à MS2 SDK et MS1 SDK. De cette façon, aucune communication (SYNC OU ASYNC) n'est faite directement entre MS1 et MS2 et la duplication des données est également évitée.

Bien sûr, la solution ci-dessus ne concerne que les UUID/GUID partagés entre les microservices. Pour les données complètes, un bus d'événements est utilisé pour distribuer les événements et les données entre les microservices de manière asynchrone (modèle d'approvisionnement en événements).

Inspiration : https://aws.amazon.com/api-gateway/ et https://getkong.org/

Questions et documentation connexes :

2voto

iluwatar Points 514

D'après la question et les commentaires, je comprends que vous essayez de réorganiser les blocs pour améliorer les performances du système. Comme décrit dans les diagrammes, vous suggérez qu'au lieu que le microservice1 interroge le microservice2, la passerelle interroge le microservice2 puis le microservice1 en lui fournissant les informations du microservice2.

En tant que tel, je ne vois pas comment cela pourrait augmenter de manière significative les performances du système, mais le changement semble plutôt déplacer la logique.

Pour remédier à cette situation, il faut améliorer les performances du microservice critique2. Cela peut être fait en profilant et en optimisant le logiciel du microservice2 (mise à l'échelle verticale) et/ou vous pouvez introduire l'équilibrage de charge (mise à l'échelle horizontale) et exécuter le microservice2 sur plusieurs serveurs. Le modèle de conception à utiliser dans ce cas est le suivant Modèle d'équilibrage de la charge des services .

2voto

Leonel Points 766

Vérifiez la section Solution possible sur ma question :

L'idée est d'utiliser la passerelle comme une passerelle api de traitement des demandes qui mettra en cache certaines réponses HTTP de MS1 et MS2 et les utilisera comme réponse à MS2 SDK et MS1 SDK. De cette façon, aucune communication (SYNC OU ASYNC) n'est faite directement entre MS1 et MS2 et la duplication des données est également évitée.

Inspiration : https://aws.amazon.com/api-gateway/ et https://getkong.org/

1voto

lud1977 Points 473

Il est toutefois difficile de juger de la viabilité d'une solution sans regarder "à l'intérieur" des boîtes :

  • Si la seule chose qui vous intéresse ici est d'empêcher le frontend de potentiellement altérer les données, vous pouvez créer une sorte de "signature" du paquet de données envoyé par MS2 au frontend et propager la signature à MS1 avec le paquet. La signature peut être un hachage du paquet contaténé avec un nombre pseudo-aléatoire généré de manière déterministe à partir d'une graine partagée par les microservices (ainsi MS1 peut recréer le même nombre pseudo-aléatoire que MS2 sans avoir besoin d'une requête HTTP B2B supplémentaire, puis vérifier l'intégrité du paquet).

  • La première idée qui me vient à l'esprit est de vérifier si la propriété des données pourrait être modifiée. Si MS1 doit fréquemment accéder à un sous-ensemble de données de MS2, il est PEUT-ÊTRE possible de déplacer la propriété de ce sous-ensemble de MS2 à MS1.

  • Dans un monde idéal, les microservices devraient être complètement autonomes, chacun ayant sa propre couche de persistance et un système de réplication en place. Vous dites qu'un courtier n'est pas une solution viable, alors qu'en est-il d'une couche de données partagée ?

J'espère que cela vous aidera !

1voto

ILICH Points 161

Vous pouvez envisager de remplacer votre mode synchrone de communication B2B par un mode asynchrone utilisant le modèle de publication et d'abonnement. Dans cette situation, le fonctionnement des services sera plus indépendant et vous n'aurez peut-être pas besoin d'effectuer des requêtes B2B en permanence.

La façon dont vous le rendez plus rapide dans un système distribué est par la dénormalisation. Si ms2data change rarement, c'est-à-dire que vous le lisez plus que vous ne le réécrivez, vous devez le dupliquer à travers les services. En faisant cela, vous réduirez la latence et le couplage temporel. L'aspect du couplage peut être encore plus important que la vitesse dans de nombreuses situations.

Si ms2data est une information sur un produit, alors ms2 doit publier l'événement ProductCreated contenant ms2data sur un bus. Ms1 devrait être abonné à cet événement et stocker ms2data dans sa propre base de données. Maintenant, chaque fois que ms1 a besoin de ms2data, il va simplement le lire localement sans avoir besoin d'effectuer des requêtes à ms2. C'est ce que signifie le découplage temporel. Lorsque vous suivez ce modèle, votre solution devient plus tolérante aux pannes et l'arrêt de ms2 n'influencera en rien ms1.

Envisagez de lire un bonne série d'articles qui décrivent les problèmes derrière la communication synchrone dans l'architecture des microservices.

Questions connexes sur le SO ici et ici discutant de problèmes assez similaires, pensez à y jeter un coup d'œil.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X