Je suis relativement nouveau dans l'architecture de microservices. Nous avons une application Web de taille moyenne et je pèse les avantages et les inconvénients de la décomposer en microservices au lieu d'un système monolithique que nous avons maintenant aller de l'avant.
Pour autant que je le comprends, considérons les microservices A
et B
chacun d'eux s'appuie sur un sous-ensemble de données que l'autre possède. Si un message est publié en A
disant que quelque chose a changé, B
peut consommer ce message et répliquer une copie locale des A
informations de et l'utiliser pour faire tout ce qui B
doit être fait.
Cependant, que se B
passe- t-il si descend / échoue et après un certain temps, revient à nouveau. Pendant ce temps d'arrêt, A
a publié deux autres messages. Comment B
sait comment mettre à jour sa copie locale des A
informations de?
Certes, si B
est le seul consommateur de A
la file d'attente de, alors il peut commencer à le lire une fois qu'il sera de retour en ligne, mais que se passe-t-il s'il y a d'autres consommateurs de cette file d'attente et que ces messages sont consommés?
À titre d'exemple plus concret, si un Users
service a son adresse e-mail mise à jour alors qu'un Billing
microservice est en panne, si le Billing
microservice réapparaît, comment sait-il que l'e-mail a été mis à jour?
Lorsque les microservices reviennent, est-ce que cela fait une émission disant "Hey, je suis de retour, donnez-moi toutes vos informations actuelles?"
En général, quelles seraient les meilleures pratiques de l'industrie pour la synchronisation des données?
la source
Orders
faut-il savoir quelque choseUsers
?Réponses:
Je contesterais toute votre idée de "pousser les données vers tous les autres microservices".
Habituellement, si un service de facturation a besoin d'une adresse e-mail, il demande simplement au service d'adresse l'adresse e-mail du client spécifique. Il n'a pas besoin de conserver une copie de toutes les données d'adresse et ne sera pas informé en cas de changement. Il demande simplement et obtient la réponse des données les plus récentes.
la source
Après avoir fait un peu plus de recherche, je suis tombé sur cet article dont j'ai tiré quelques citations qui je pense sont utiles pour ce que je veux accomplir (et pour tous les futurs lecteurs). Cela offre un moyen d'adopter un modèle de programmation réactive par rapport à un modèle de programmation impératif.
Recherche d'événements
Ce que cela permet d'accomplir, c'est que si un microservice tombe en panne et que d'autres événements qui le concernent sont publiés et que les événements sont consommés par, par exemple, d'autres instances de ce microservice, lorsque ce microservice revient, il peut s'y référer
event store
pour récupérer tous les événements qu'il a manqués au cours de la période où il est tombé.Apache Kafka en tant que courtier d'événements
Envisagez l'utilisation d'Apache Kafka qui peut stocker et distribuer des milliers d'événements par seconde et dispose de mécanismes de réplication et de tolérance aux pannes intégrés. Il a une mémoire persistante d'événements qui peuvent être stockés sur le disque indéfiniment et consommés à tout moment (mais non supprimés) du sujet (la file d'attente de fantaisie de Kafka) ont été livrés à.
En fait, lorsque les consommateurs s'identifieront à Kafka, Kafka enregistrera quels messages ont été livrés à quel consommateur afin qu'il ne les réutilise plus.
Sagas
C'est alors que la saga entre en jeu. Une saga est une séquence de transactions locales. Chaque transaction locale met à jour la base de données et publie un message ou un événement pour déclencher la prochaine transaction locale dans la saga. Si une transaction locale échoue car elle enfreint une règle commerciale, la saga exécute une série de transactions compensatoires qui annulent les modifications apportées par les transactions locales précédentes. Lisez ceci pour plus d'informations.
la source
Même si je suis en retard, je voudrais mettre mes 2 cents sur l'argument car je pense que c'est un point important lorsque vous voulez évaluer la conception d'une architecture de microservices événementielle. Chaque microservice sait exactement quels sont les événements qui ont un impact sur son état et peut les attendre. Lorsque le microservice n'est pas disponible, il doit y avoir un composant qui conserve les messages nécessaires du microservice défaillant jusqu'à ce qu'il ne soit pas en mesure de les «consommer». Il s'agit en fait d'un modèle "producteur / consommateur" et non d'un modèle "publier / souscrire". Les courtiers de messages (comme Kafka, RabbitMQ, ActiveMQ, etc.) sont généralement le meilleur moyen d'obtenir ce comportement (à moins que vous n'implémentiez pas quelque chose de différent comme le sourcing d'événements) en fournissant des files d'attente persistantes et un mécanisme ack / nack.
Maintenant, le microservice sait qu'un message est finalement délivré, mais ce n'est pas suffisant: quelle est la façon dont il attend la livraison d'un seul message? peut-il gérer la livraison de plusieurs copies de la même notification d'événement? C'est une question de livraison sémantique (au moins une fois, exactement une fois)
Dernières pensées):
Lorsque vous ajoutez un microservice à votre architecture qui doit consommer les événements des autres, vous devez effectuer la première synchronisation
Même le courtier peut échouer, dans ce cas, les messages sont perdus
pour les deux scénarios, il serait utile de disposer de mécanismes simples pour réhydrater votre état de microservice. Il peut s'agir d'une API REST ou d'un script qui envoie des messages, mais le plus important est d'avoir des moyens d'effectuer une tâche de maintenance
la source
Vous pouvez remplacer une file d'attente d'événements normale par un modèle éditeur / abonné, dans lequel le
A
service publie un nouveau message de la rubrique T et leB
type de microservices s'abonnerait à la même rubrique.Idéalement, ce
B
serait un service sans état, et il utiliserait un service de persistance détaché, de sorte qu'uneB
instance de service défaillante serait remplacée par la création d'une ou plusieursB
instances de service pour continuer son travail, en lisant à partir du même service de persistance partagé.la source
Si vous vouliez que B puisse accéder aux données internes de A, vous feriez mieux de lui donner simplement accès aux bases de données internes de A.
Cependant, vous ne devriez pas faire cela, le point essentiel d'une architecture orientée service est que le service B ne peut pas voir l'état interne du service A et est limité à effectuer des requêtes via les API REST (et vice versa).
Dans votre cas, vous pourriez avoir un service de données utilisateur, qui a la responsabilité de stocker toutes les données utilisateur. D'autres services qui souhaitent utiliser ces données ne le demandent que lorsqu'ils en ont besoin et n'en conservent pas de copie locale (ce qui est vraiment utile si vous pensez à la conformité au RGPD). Le service de données utilisateur peut prendre en charge des opérations CRUD simples comme «Créer un nouvel utilisateur» ou «Changer le nom pour user_id 23» ou il peut avoir des opérations plus complexes, «Trouver tous les utilisateurs standard avec un anniversaire à venir dans les 2 prochaines semaines et leur donner statut d'essai premium ". Désormais, lorsque votre service de facturation doit envoyer un e-mail à l'utilisateur 42, il demande au service de données utilisateur "Quelle est l'adresse e-mail de user_id 42", utilise ses données internes avec toutes les informations de facturation pour créer l'e-mail, puis peut transmettre le message adresse e-mail et corps d'un serveur de messagerie.
la source