Modifier

Modèle de chorégraphie

Azure Event Grid
Azure Service Bus

Faites participer chaque composant du système au processus décisionnel concernant le flux de travail d’une transaction, au lieu de s’appuyer sur un point de contrôle central.

Contexte et problème

Dans l’architecture de microservices, il est fréquent qu’une application cloud soit divisée en plusieurs petits services qui fonctionnent ensemble pour traiter une transaction commerciale de bout en bout. Pour réduire le couplage entre les services, chaque service est responsable d’une seule opération commerciale. Parmi les avantages, citons le développement plus rapide, la base de code plus petite et la scalabilité. Toutefois, la conception d’un workflow efficace et évolutif est un défi et nécessite souvent une communication interservice complexe.

Les services communiquent entre eux à l’aide d’API bien définies. Même une seule opération métier peut entraîner plusieurs appels point à point parmi tous les services. Un modèle commun pour la communication consiste à utiliser un service centralisé qui agit en tant qu’orchestrateur. Il reconnaît toutes les requêtes entrantes et délègue les opérations aux services respectifs. Cela permet également de gérer le flux de travail de la totalité de la transaction commerciale. Chaque service effectue simplement une opération et n’est pas conscient du flux de travail global.

Le modèle d’orchestrateur réduit la communication point à point entre les services mais présente des inconvénients en raison du couplage étroit entre l’orchestrateur et les autres services qui participent au traitement de la transaction commerciale. Pour exécuter des tâches dans une séquence, l’orchestrateur doit avoir une connaissance du domaine concernant les responsabilités de ces services. Si vous souhaitez ajouter ou supprimer des services, la logique existante s’arrêtera et vous devrez reconnecter certaines parties du chemin de communication. Bien que vous puissiez configurer le flux de travail, ajouter ou supprimer facilement des services avec un orchestrateur bien conçu, une telle implémentation est complexe et difficile à gérer.

Traitement d’une requête à l’aide d’un orchestrateur central

Solution

Laissez chaque service décider du moment et de la façon dont une opération métier est traitée, au lieu de dépendre d’un orchestrateur central.

L’une des façons d’implémenter une chorégraphie consiste à utiliser le modèle de messagerie asynchrone pour coordonner les opérations de l’entreprise.

Traitement d’une requête à l’aide d’un chorégraphe

Une requête client publie des messages dans une file d’attente de messages. À mesure que les messages arrivent, ils sont envoyés aux abonnés ou aux services qui s’intéressent à ce message. Chaque service abonné effectue son opération comme indiqué par le message et répond à la file d’attente par une réussite ou un échec de l’opération. En cas de réussite, le service peut envoyer un message à la même file d’attente ou à une file d’attente de messages différente pour qu’un autre service puisse continuer le flux de travail si nécessaire. Si une opération échoue, le bus de messages peut retenter cette opération.

De cette façon, les services orchestrent le flux de travail entre eux sans dépendre d’un orchestrateur ou d’une communication directe.

Étant donné qu’il n’existe pas de communication point à point, ce modèle permet de réduire le couplage entre les services. En outre, il peut supprimer le goulot d’étranglement de performances provoqué par l’orchestrateur lorsqu’il doit traiter toutes les transactions.

Quand utiliser ce modèle

Utilisez le modèle de chorégraphie si vous prévoyez de mettre à jour ou de remplacer fréquemment des services, puis ajoutez ou supprimez certains services à la fin. L’ensemble de l’application peut être modifié avec moins d’effort et une interruption minimale des services existants.

Pensez à utiliser ce modèle si vous rencontrez des goulots d’étranglement de performances dans l’orchestrateur central.

Ce modèle est un modèle naturel pour l’architecture serverless dans laquelle tous les services peuvent être éphémères ou pilotés par des événements. Les services peuvent s’exécuter en raison d’un événement, réaliser leur tâche et être supprimés à la fin de la tâche.

Problèmes et considérations

La décentralisation de l’orchestrateur peut provoquer des problèmes lors de la gestion du flux de travail.

Si un service ne parvient pas à effectuer une opération commerciale, la récupération suivant cet échec peut être difficile. L’une des méthodes consiste à faire en sorte que le service indique un échec en déclenchant un événement. Un autre service s’abonne à ces événements ayant échoué et prend les mesures nécessaires, telles que l’application de transactions de compensation pour annuler les opérations réussies dans une requête. Le service défaillant peut également échouer à déclencher un événement en cas de défaillance. Dans ce cas, envisagez d’utiliser un mécanisme de nouvelle tentative ou d’expiration du délai d’attente pour reconnaître cette opération comme un échec. Consultez la section d’exemples.

Il est facile d’implémenter un flux de travail lorsque vous souhaitez traiter en parallèle des opérations commerciales indépendantes. Vous pouvez utiliser un seul bus de messages. Toutefois, le flux de travail peut devenir compliqué lorsque la chorégraphie doit se produire dans une séquence. Par exemple, le service C peut démarrer son opération uniquement après que le service A et le service B ont terminé leurs opérations avec succès. Une approche consiste à avoir plusieurs bus ou files d'attente de messages qui reçoivent les messages dans l’ordre requis. Pour plus d’informations, consultez la section Exemple.

Le modèle de chorégraphie devient un défi si le nombre de services augmente rapidement. Étant donné le nombre élevé de parties mobiles indépendantes, le flux de travail entre les services tend à se complexifier. En outre, le suivi distribué devient difficile.

L’orchestrateur centralise la gestion de la résilience du flux de travail et peut devenir un point de défaillance unique. En revanche, pour la chorégraphie, le rôle est distribué entre tous les services et la résilience devient moins robuste.

Chaque service n’est pas uniquement responsable de la résilience de son fonctionnement, il est également responsable du flux de travail. Cette responsabilité peut être fastidieuse pour le service et difficile à implémenter. Chaque service doit effectuer de nouvelles tentatives pour les échecs temporaires, non transitoires et de délais d’expiration, afin que la requête se termine correctement, si nécessaire. En outre, le service doit être assidu pour communiquer la réussite ou l’échec de l’opération afin que d’autres services puissent agir en conséquence.

Conception de la charge de travail

Un architecte doit évaluer la façon dont le modèle de chorégraphie peut être utilisé dans la conception de leurs charges de travail pour se conformer aux objectifs et principes abordés dans les piliers d’Azure Well-Architected Framework. Par exemple :

Pilier Comment ce modèle soutient les objectifs des piliers.
L’excellence opérationnelle permet de fournir une qualité de charge de travail grâce à des processus standardisés et à la cohésion d’équipe. Les composants distribués de ce modèle étant autonomes et conçus pour être remplaçables, il est possible de modifier la charge de travail en limitant les modifications globales du système.

- OE :04 Outils et processus
L’efficacité des performances permet à votre charge de travail de répondre efficacement aux demandes grâce à des optimisations de la mise à l’échelle, des données, du code. Ce modèle offre une solution de rechange en cas de goulots d’étranglement des performances dans une topologie d’orchestration centralisée.

- PE :02 Planification de la capacité
- PE :05 Mise à l’échelle et partitionnement

Comme pour toute autre décision de conception, il convient de prendre en compte les compromis par rapport aux objectifs des autres piliers qui pourraient être introduits avec ce modèle.

Exemple

Cet exemple montre le modèle de chorégraphie en créant une charge de travail native dans le cloud, pilotée par les événements, qui exécute des fonctions avec des microservices. Lorsqu’un client demande l’expédition d’un colis, la charge de travail affecte un drone. Une fois que le drone est prêt à récupérer le colis, le processus de livraison commence. Pendant le transit, la charge de travail gère la livraison jusqu’à ce que sont état soit « expédié ».

Cet exemple est une refactorisation de l'implémentation de livraison par drones qui remplace le modèle d'orchestrateur par celui de chorégraphie.

Diagramme d’un exemple de charge de travail native dans le cloud, pilotée par les événements, qui implémente un modèle de chorégraphie

Le service d’ingestion gère les demandes du client et les convertit en messages, y compris les détails de livraison. Les transactions commerciales sont lancées une fois ces nouveaux messages consommés.

Une transaction commerciale avec un seul client nécessite trois opérations commerciales distinctes : la création ou la modification d'un colis, l’affectation d’un drone à la livraison du colis et la bonne gestion de la livraison, qui consiste à vérifier la marchandise et sensibiliser les personnes concernées lors de l’expédition. Ces opérations sont effectuées par trois microservices : Colis, Planification des drones et Livraison. Au lieu d’un orchestrateur central, les services communiquent entre eux à l'aide d'un système de messagerie. Chaque service est chargé de mettre en œuvre en amont un protocole qui coordonne de manière décentralisée le flux de travail commercial.

Conception

La transaction commerciale est traitée dans une séquence par le biais de plusieurs tronçons. Chaque tronçon partage un seul bus de messages entre tous les services d’entreprise.

Lorsqu’un client envoie une demande de livraison via un point de terminaison HTTP, le service d'ingestion la reçoit et la convertit en message, qui est ensuite publié dans le bus de messages partagé. Les services d’entreprise abonnés consommeront les nouveaux messages ajoutés au bus. Lors de la réception du message, les services commerciaux peuvent terminer l’opération par une réussite, un échec ou une expiration du délai d’attente de la requête. En cas de réussite, les services répondent au bus avec le code d’état Ok, déclenchent un nouveau message d’opération et l’envoie au bus de messages du tronçon suivant. En cas d’échec ou d’expiration, le service signale l’échec en envoyant le code de motif au bus de messages. Par ailleurs, le message va être mis en lettre morte à des fins de gestion ultérieure. Les messages qui n’ont pas pu être reçus ou traités dans un délai raisonnable et approprié sont également déplacés vers la file d'attente des lettres mortes.

La conception utilise plusieurs bus de messages pour traiter l’ensemble de la transaction commerciale. Microsoft Azure Service Bus et Microsoft Azure Event Grid vous permettent de fournir la plateforme de service de messagerie pour cette conception. La charge de travail est déployée sur Azure Container Apps, qui héberge les fonctions Azure d’ingestion et les applications qui gèrent le traitement piloté par les événements qui exécute la logique commerciale.

Grâce à la conception, la chorégraphie se déroule dans une séquence. L'espace de noms Azure Service Bus unique contient une rubrique avec deux abonnements et une file d’attente prenant en compte les sessions. Le service d’ingestion publie des messages dans la rubrique. Le service Colis et le service de planification des drones s’abonnent à la rubrique et publient des messages qui communiquent le succès à la file d’attente. Inclure un identifiant de session commun, qui inclut un GUID associé à l'identifiant de livraison, permet de traiter de manière ordonnée les séquences non liées de messages connexes. Le service de livraison attend deux messages connexes par transaction. Le premier message indique que le colis est prêt à être expédié, et le deuxième signal qu’un drone est attribué.

Cette conception utilise Azure Service Bus pour gérer les messages à valeur élevée à ne pas perdre ni dupliquer pendant l’ensemble du processus de livraison. Lorsque le colis est expédié, l'état est modifié dans Azure Event Grid. Dans cette conception, l’expéditeur de l’événement n’a aucune attente quant à la façon dont le changement d’état est géré. Les services d’organisation en aval qui ne sont pas inclus dans le cadre de cette conception peuvent écouter ce type d’événement. Ils peuvent également réagir à l’exécution d’une logique d’objectif commercial spécifique (autrement dit, envoyer l’état de la commande livrée à l’utilisateur).

Si vous envisagez de le déployer dans un autre service de calcul, comme AKS, l'application du modèle pub-sub boilplate pourrait être mise en œuvre avec deux conteneurs dans le même pod. Un conteneur exécute l’ambassadeur qui interagit avec le bus de messages de votre choix, tandis que l’autre exécute la logique commerciale. L’approche avec deux conteneurs dans le même pod améliore les performances et la scalabilité. L’ambassadeur et le service commercial partagent le même réseau, ce qui permet une faible latence et un débit élevé.

Pour éviter les tentatives en cascade qui pourraient conduire à des efforts multiples, les services d’entreprise doivent immédiatement signaler les messages inacceptables. Il est possible d’enrichir ces messages à l’aide de codes de raison connus ou d’un code d’application défini, afin qu’il puisse être déplacé vers une file d’attente de lettres mortes. Envisagez de gérer les problèmes de cohérence qui implémentent Saga à partir de services en aval. Par exemple, un autre service pourrait traiter les messages en lettres mortes à des fins de remédiation uniquement en exécutant une transaction de compensation, de rétablissement ou de pivot.

Les services commerciaux sont idempotents pour s’assurer que les nouvelles tentatives n’entraînent pas la duplication des ressources. Par exemple, le service de package utilise des opérations upsert pour ajouter des données au magasin de données.

Tenez compte de ces modèles dans votre conception pour la chorégraphie.