2 votes

DB Transaction and Integrations Events dispatch - how to make it atomic ?

Je conçois un système avec de multiples contextes délimités (microservices). J'aurai 2 types d'événements.

  • Domain Events qui se produit "en mémoire" dans le cadre d'une transaction unique (synchronisation)
  • Integration Events, qui sont utilisés entre des contextes délimités (asynchrones)

Mon problème est de savoir comment s'assurer qu'une fois la transaction validée (à ce stade, je suis sûr que toutes les transactions sont validées), l'opération est validée. Domain Events ont été traitées avec succès) que Integration Events sont également couronnés de succès.

Lorsque ma transaction est validée, j'envoie normalement Integration Events (par exemple, dans la file d'attente), mais il est possible que cette file d'attente soit également en panne, de sorte que la transaction qui vient d'être engagée doit être "annulée". Comment cela se passe-t-il ?

La seule solution qui me vient à l'esprit est de stocker les Integration Events à la même base de données, dans la même transaction, puis de traiter le Integration Events et les pousser dans la file d'attente - ce serait quelque chose comme "utiliser la base de données actuelle, comme une pré-file d'attente, avant de la pousser dans la file d'attente". La vraie file d'attente (cependant, j'ai lu que l'utilisation de la base de données pour cela est un anti-modèle).

Existe-t-il un modèle (une approche fiable) pour s'assurer que les deux : Validation de la transaction y Message poussé dans la file d'attente est une opération atomique ?

EDIT Après avoir lu https://devblogs.microsoft.com/cesardelatorre/domain-events-vs-integration-events-in-domain-driven-design-and-microservices-architectures/ L'auteur suggère en fait l'approche de la "pré-queue" dans la même base de données (il l'appelle "prêt à publier l'événement").

2voto

Sihoon Kim Points 805

Sortie de caisse modèle de boîte d'envoi transactionnelle .

Ce modèle crée une file d'attente préalable. Mais l'avantage est que la transmission des messages de la pré-file d'attente à la file d'attente réelle est entièrement découplée. Au lieu de cela, vous avez un intermédiaire appelé relais de messages qui lit vos journaux de transactions et pousse vos événements vers la file d'attente réelle. Maintenant, puisque l'envoi de messages et vos événements de domaine sont entièrement découplés, vous pouvez faire tous vos événements de domaine dans une seule transaction.

Et assurez-vous que tous vos services sont idempontent (même résultat malgré des appels dupliqués). Ce modèle de boîte de sortie transactionnelle garantit que les messages sont publiés, mais dans le cas où le relais de message échoue juste après la publication (avant l'accusé de réception), le même événement est publié à nouveau.

Les services idempotents sont également nécessaires dans d'autres scénarios. Le bus d'événements (la vraie file d'attente) pourrait avoir le même problème. Le bus d'événements propage les événements, les services accusent réception, puis il y a une erreur de réseau, et comme le bus d'événements n'est pas accusé réception, le même événement est envoyé à nouveau.

En fait, l'idempotence pourrait à elle seule résoudre le problème. Une fois que le calcul des événements du domaine est terminé (transaction unique), si la publication d'un message échoue, le service peut simplement envoyer une erreur sans retour en arrière. Puisque l'événement n'est pas acquitté, le bus d'événements enverra à nouveau le même événement. Puisque le service est idempotent, la même transaction de base de données ne se produira pas deux fois, elle sera écrasée ou mieux (devrait) être ignorée et passer directement à la publication et à l'acquittement du message.

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