Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.
Modèle d’orchestration de saga
Intention
Le modèle d’orchestration de saga utilise un coordinateur central (orchestrateur) pour aider à préserver l’intégrité des données dans les transactions distribuées qui couvrent plusieurs services. Dans une transaction distribuée, plusieurs services peuvent être appelés avant qu’une transaction ne soit terminée. Lorsque les services stockent des données dans différents magasins de données, il peut être difficile de maintenir la cohérence des données entre ces magasins de données.
Motivation
Une transaction est une unité de travail unique qui peut impliquer plusieurs étapes, toutes les étapes étant entièrement exécutées ou aucune étape n’étant exécutée, ce qui permet à un magasin de données de conserver son état cohérent. Les termes atomicité, cohérence, isolement et durabilité (ACID) définissent les propriétés d’une transaction. Les bases de données relationnelles fournissent des transactions ACID pour maintenir la cohérence des données.
Pour maintenir la cohérence d’une transaction, les bases de données relationnelles utilisent la méthode de validation en deux phases (2PC). Il s’agit d’une phase de préparation et d’une phase de validation.
-
Au cours de la phase de préparation, le processus de coordination demande aux processus participants à la transaction (participants) de promettre de valider ou d’annuler la transaction.
-
Dans la phase de validation, le processus de coordination demande aux participants de valider la transaction. Si les participants ne parviennent pas à s’engager lors de la phase de préparation, la transaction est annulée.
Dans les systèmes distribués qui suivent un modèle de database-per-service conception, la validation en deux phases n'est pas une option. En effet, chaque transaction est distribuée entre différentes bases de données et aucun contrôleur ne peut coordonner un processus similaire à la validation en deux phases dans les magasins de données relationnels. Dans ce cas, une solution consiste à utiliser le modèle d’orchestration de saga.
Applicabilité
Utilisez le modèle d’orchestration de saga lorsque :
-
Votre système a besoin de l’intégrité et de la cohérence des données dans les transactions distribuées qui s’étendent sur plusieurs magasins de données.
-
Le magasin de données ne propose pas de 2PC pour les transactions ACID, et que la mise en œuvre de 2PC dans les limites de l’application est une tâche complexe.
-
Vous avez des bases de données NoSQL qui ne fournissent pas de transactions ACID et vous devez mettre à jour plusieurs tables au cours d’une seule transaction.
Problèmes et considérations
-
Complexité : les transactions compensatoires et les nouvelles tentatives ajoutent de la complexité au code de l’application, ce qui peut entraîner des frais de maintenance.
-
Cohérence à terme : le traitement séquentiel des transactions locales aboutit à une cohérence à terme, ce qui peut être un défi dans les systèmes nécessitant une forte cohérence. Vous pouvez résoudre ce problème en définissant les attentes de vos équipes métier en ce qui concerne le modèle de cohérence ou en optant pour un magasin de données offrant une forte cohérence.
-
Idempotence : les participants à la saga doivent être idempotents pour permettre des exécutions répétées en cas de défaillances transitoires causées par des pannes inattendues ou des défaillances de l’orchestrateur.
-
Isolement des transactions : la saga n’est pas isolée des transactions. L’orchestration simultanée de transactions peut entraîner l’obsolescence des données. Nous vous recommandons d’utiliser le verrouillage sémantique pour gérer de tels scénarios.
-
Observabilité : l’observabilité fait référence à la journalisation et au suivi détaillés pour résoudre les problèmes liés au processus d’exécution et d’orchestration. Cela devient important lorsque le nombre de participants à la saga augmente, ce qui complique le débogage.
-
Problèmes de latence : les transactions compensatoires peuvent ajouter de la latence au temps de réponse global lorsque la saga comporte plusieurs étapes. Évitez les appels synchrones dans de tels cas.
-
Point de défaillance unique : l’orchestrateur peut devenir un point de défaillance unique, car il coordonne l’ensemble de la transaction. Dans certains cas, le modèle de chorégraphie de saga est préféré en raison de ce problème.
Mise en œuvre
Architecture de haut niveau
Dans le schéma d’architecture suivant, l’orchestrateur de saga compte trois participants : le service de commande, le service d’inventaire et le service de paiement. Trois étapes sont nécessaires pour terminer la transaction : T1, T2 et T3. L’orchestrateur de saga connaît les étapes et les exécute dans l’ordre requis. Lorsque l’étape T3 échoue (échec de paiement), l’orchestrateur exécute les transactions compensatoires C1 et C2 pour rétablir les données dans leur état initial.
Vous pouvez utiliser AWS Step Functions
Mise en œuvre à l’aide des services AWS
L’exemple de solution utilise le flux de travail standard de Step Functions pour implémenter le modèle d’orchestration de saga.
Lorsqu’un client appelle l’API, la fonction Lambda est invoquée et le prétraitement est effectué dans la fonction Lambda. La fonction lance le flux de travail Step Functions pour commencer à traiter la transaction distribuée. Si aucun prétraitement n’est requis, vous pouvez lancer le flux de travail Step Functions directement
L’utilisation de Step Functions atténue le problème du point de défaillance unique, inhérent à la mise en œuvre du modèle d’orchestration de saga. Step Functions intègre une tolérance aux pannes et maintient la capacité de service dans plusieurs zones de disponibilité dans chaque Région AWS afin de protéger les applications contre les pannes individuelles de machines ou de centres de données. Cela permet de garantir une haute disponibilité à la fois pour le service lui-même et pour le flux de travail des applications qu’il gère.
Flux de travail Step Functions
La machine d’état Step Functions vous permet de configurer les exigences de flux de contrôle basées sur les décisions pour la mise en œuvre du modèle. Le flux de travail Step Functions appelle les différents services pour le placement des commandes, la mise à jour de l’inventaire et le traitement des paiements afin de terminer la transaction et envoie une notification d’événement pour un traitement ultérieur. Le flux de travail Step Functions agit en tant qu’orchestrateur pour coordonner les transactions. Si le flux de travail contient des erreurs, l’orchestrateur exécute les transactions compensatoires pour garantir le maintien de l’intégrité des données dans tous les services.
Le schéma suivant illustre les étapes du flux de travail Step Functions. Les étapes Place Order
, Update Inventory
et Make Payment
indiquent le chemin à suivre pour réussir. La commande est passée, l’inventaire est mis à jour et le paiement est traité avant qu’un état Success
ne soit renvoyé à l’appelant.
Les fonctions Lambda Revert Payment
, Revert Inventory
et Remove
Order
indiquent les transactions compensatoires que l’orchestrateur exécute en cas d’échec d’une étape du flux de travail. Si le flux de travail échoue à l’étape Update Inventory
, l’orchestrateur appelle les étapes Revert
Inventory
et Remove Order
avant de renvoyer un état Fail
à l’appelant. Ces transactions compensatoires garantissent le maintien de l’intégrité des données. L’inventaire revient à son niveau initial et la commande est annulée.
Exemple de code
L’exemple de code suivant montre comment créer un orchestrateur de saga à l’aide de Step Functions. Pour consulter le code complet, consultez le GitHubréférentiel
Définitions de tâche
var successState = new Succeed(this,"SuccessState"); var failState = new Fail(this, "Fail"); var placeOrderTask = new LambdaInvoke(this, "Place Order", new LambdaInvokeProps { LambdaFunction = placeOrderLambda, Comment = "Place Order", RetryOnServiceExceptions = false, PayloadResponseOnly = true }); var updateInventoryTask = new LambdaInvoke(this,"Update Inventory", new LambdaInvokeProps { LambdaFunction = updateInventoryLambda, Comment = "Update inventory", RetryOnServiceExceptions = false, PayloadResponseOnly = true }); var makePaymentTask = new LambdaInvoke(this,"Make Payment", new LambdaInvokeProps { LambdaFunction = makePaymentLambda, Comment = "Make Payment", RetryOnServiceExceptions = false, PayloadResponseOnly = true }); var removeOrderTask = new LambdaInvoke(this, "Remove Order", new LambdaInvokeProps { LambdaFunction = removeOrderLambda, Comment = "Remove Order", RetryOnServiceExceptions = false, PayloadResponseOnly = true }).Next(failState); var revertInventoryTask = new LambdaInvoke(this,"Revert Inventory", new LambdaInvokeProps { LambdaFunction = revertInventoryLambda, Comment = "Revert inventory", RetryOnServiceExceptions = false, PayloadResponseOnly = true }).Next(removeOrderTask); var revertPaymentTask = new LambdaInvoke(this,"Revert Payment", new LambdaInvokeProps { LambdaFunction = revertPaymentLambda, Comment = "Revert Payment", RetryOnServiceExceptions = false, PayloadResponseOnly = true }).Next(revertInventoryTask); var waitState = new Wait(this, "Wait state", new WaitProps { Time = WaitTime.Duration(Duration.Seconds(30)) }).Next(revertInventoryTask);
Définitions de Step Functions et des machines d’état
var stepDefinition = placeOrderTask .Next(new Choice(this, "Is order placed") .When(Condition.StringEquals("$.Status", "ORDER_PLACED"), updateInventoryTask .Next(new Choice(this, "Is inventory updated") .When(Condition.StringEquals("$.Status", "INVENTORY_UPDATED"), makePaymentTask.Next(new Choice(this, "Is payment success") .When(Condition.StringEquals("$.Status", "PAYMENT_COMPLETED"), successState) .When(Condition.StringEquals("$.Status", "ERROR"), revertPaymentTask))) .When(Condition.StringEquals("$.Status", "ERROR"), waitState))) .When(Condition.StringEquals("$.Status", "ERROR"), failState)); var stateMachine = new StateMachine(this, "DistributedTransactionOrchestrator", new StateMachineProps { StateMachineName = "DistributedTransactionOrchestrator", StateMachineType = StateMachineType.STANDARD, Role = iamStepFunctionRole, TracingEnabled = true, Definition = stepDefinition });
GitHub référentiel
Pour une implémentation complète de l'exemple d'architecture pour ce modèle, consultez le GitHub référentiel à l'adresse https://github.com/aws-samples/ saga-orchestration-netcore-blog
Références du blog
Contenu connexe
Vidéos
La vidéo suivante explique comment implémenter le modèle d'orchestration de la saga en utilisant AWS Step Functions.