Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Faites en sorte que chaque service décide quand et comment traiter une opération métier, au lieu de dépendre d’un orchestrateur central. Cette approche simplifie la logique de flux de travail et distribue les responsabilités entre les composants d’un système.
Contexte et problème
Vous divisez généralement une application basée sur le cloud en plusieurs petits services qui fonctionnent ensemble pour traiter une transaction métier de bout en bout. Une seule opération au sein d’une transaction peut entraîner plusieurs appels point à point entre tous les services. Dans l’idéal, ces services sont faiblement couplés. Il est difficile de concevoir un flux de travail distribué, efficace et évolutif, car il implique une communication interservice complexe.
Un modèle commun pour la communication consiste à utiliser un service centralisé ou un orchestrateur. Les requêtes entrantes passent par l’orchestrateur qui délègue les opérations aux services respectifs. Chaque service termine ses responsabilités et n'est pas au courant du flux de travail global.
Vous implémentez généralement le modèle d’orchestrateur en tant que logiciel personnalisé qui a des connaissances sur les responsabilités des services au sein du système. L’un des avantages de cette approche est que l’orchestrateur peut consolider l’état d’une transaction en fonction des résultats des opérations individuelles effectuées par les services en aval.
Cette approche crée également des obstacles. L’ajout ou la suppression de services risque de rompre la logique existante, parce qu’il faut reconnecter certaines parties du chemin de communication. Cette dépendance complique la mise en œuvre de l’orchestrateur ainsi que sa maintenance. L’orchestrateur peut affecter négativement la fiabilité de la charge de travail. Sous charge, il peut générer des goulets d’étranglement en matière de performances et constituer le point de défaillance unique (SPoF). Lorsque l’orchestrateur échoue ou devient surchargé, l’échec peut se propager à tous les services en aval dépendants.
Solution
Déléguer la logique de gestion des transactions entre les services. Laissez chaque service participer au flux de travail de communication pour une opération métier et décider quand et comment le traiter.
Le modèle chorégraphique réduit la dépendance vis-à-vis des logiciels personnalisés qui centralisent le flux de travail de communication. Les composants implémentent une logique commune lorsqu’ils chorégraphient le flux de travail entre eux sans communiquer directement entre eux.
Une façon courante d’implémenter la chorégraphie consiste à utiliser un répartiteur de messages qui met en mémoire tampon les requêtes jusqu’à ce que les composants en aval les réclament et les traitent. L’image suivante montre la gestion des demandes par le biais d’un modèle d’abonné à l’éditeur.
Les demandes d’un client sont mises en file d’attente sous forme de messages dans un répartiteur de messages.
Les services ou l’abonné interrogent le répartiteur pour déterminer s’il peut traiter ce message en fonction de sa logique métier implémentée. Le répartiteur peut également envoyer des messages aux abonnés intéressés par ce message.
Chaque service abonné effectue son opération comme le message l'indique et répond au répartiteur par un message indiquant la réussite ou l’échec de l'opération.
Si l’opération réussit, le service peut publier un message dans la même file d’attente ou une autre file d’attente de messages afin qu’un autre service puisse continuer le flux de travail si nécessaire. Si l’opération échoue, le service publie un message d’échec. Les services qui s’abonnent à ce message peuvent exécuter des actions de compensation prédéfinies pour l’opération ayant échoué ou l’intégralité de la transaction.
Problèmes et considérations
Prenez en compte les points suivants lorsque vous choisissez comment implémenter ce modèle :
Complexité de la gestion des défaillances. Les composants d’une application peuvent gérer des tâches atomiques et dépendre d’autres parties du système. L’échec d’un composant peut affecter d’autres composants, ce qui peut entraîner des retards lors de la fin de la demande globale.
Pour gérer correctement les défaillances, vous implémentez une logique de gestion des défaillances, ce qui introduit une complexité. La logique de gestion des défaillances, telle que la compensation des transactions, est également sujette aux défaillances.
Processus séquentiels. Ce modèle convient à un flux de travail qui traite des opérations métier indépendantes en parallèle. Le workflow peut devenir compliqué lorsque la chorégraphie doit se produire dans une séquence. Par exemple, service D peut démarrer son opération uniquement une fois que Service B et Service C ont terminé leurs opérations avec succès.
Observabilité à grande échelle. Ce modèle présente des défis si le nombre de services augmente rapidement. De nombreuses parties mobiles indépendantes compliquent le flux de travail entre les services. Sans orchestrateur central détenant l’état complet des transactions, aucun composant unique n’a une vue complète d’une opération métier en vol. Vous devez utiliser de manière cohérente le suivi distribué et les identificateurs de corrélation pour maintenir l’observabilité.
Communication du gestionnaire de résilience. Dans une architecture pilotée par un orchestrateur, le composant central peut déléguer des fonctions de résilience, telles que la gestion des nouvelles tentatives en cas d’échecs temporaires, permanents ou dus à un dépassement de délai, à un gestionnaire dédié de la résilience.
Lorsque vous supprimez l’orchestrateur dans une conception basée sur la chorégraphie, les composants en aval ne prennent pas en charge la résilience. Ils restent centralisés dans le gestionnaire de résilience. Toutefois, les composants en aval doivent communiquer directement avec ce gestionnaire, ce qui augmente la communication point à point.
Évolution du schéma d’événement. L’évolution du schéma d’événement peut entraîner des changements cassants dans les consommateurs au fil du temps. Dans ce modèle, plusieurs services indépendants consomment les mêmes événements. Si un producteur modifie la structure des données d’un événement, il peut briser les consommateurs en aval qui dépendent de l’ancien schéma. Utilisez un registre de schémas pour gérer les contrats d’événements et utiliser l’évolution rétrocompatible à mesure que les services évoluent indépendamment.
Idempotence et ordre des événements. Au moins une fois la remise et les nouvelles tentatives peuvent produire des messages en double, et les consommateurs simultanés peuvent traiter les messages hors commande. Concevez des consommateurs de manière à ce qu’ils soient idempotents en assurant le suivi d’identifiants de message stables. Lorsque le traitement ordonné est nécessaire, utilisez des fonctionnalités broker telles que des sessions Service Bus, ou incluez des données de séquence ou de version qui permettent aux consommateurs de rejeter les événements obsolètes et de détecter les lacunes.
État atomique et publication d’événements. Un service qui met à jour son magasin de données et publie un événement dans des opérations distinctes peut valider une opération alors que l’autre échoue. Utilisez le modèle de boîte de réception transactionnelle ou un mécanisme atomique équivalent pour conserver ensemble le changement d’état et l’événement avant qu’un processus distinct publie l’événement.
Comportement émergent et rafales d’événements. Les topologies d’événements décentralisées peuvent créer un comportement émergent à grande échelle. Lorsque de nombreux services réagissent aux événements des uns aux autres, le système peut produire involontairement des boucles de rétroaction ou des tempêtes d’événements. Un événement mineur peut déclencher une cascade de réactions en aval. Pour empêcher les chaînes d’événements circulaires, utilisez des garde-fous comme le filtrage des événements, les limites de concurrence des consommateurs, la limitation et les règles explicites.
Quand utiliser ce modèle
Utilisez ce modèle dans les situations suivantes :
Les composants en aval gèrent les opérations atomiques indépendamment selon une approche fire and forget (déclencher et oublier). Chaque composant termine une tâche, puis signale l’achèvement à d’autres composants via le répartiteur de messages. Le service de lancement ne gère pas ou ne suit pas activement la tâche après l’avoir distribuée, mais les services en aval communiquent toujours les résultats par le biais d’événements.
Vous prévoyez fréquemment de mettre à jour et de remplacer les composants. Ce modèle vous permet de modifier l’application avec moins d’efforts et une interruption minimale des services existants.
Vous utilisez des architectures serverless pour les flux de travail simples. Les composants peuvent être éphémères et pilotés par des événements. Lorsqu’un événement se produit, le service crée des composants qui effectuent une tâche et le service supprime les composants une fois cette tâche terminée.
La communication entre les contextes délimités nécessite un couplage libre entre les limites du domaine. Pour la communication à l’intérieur d’un contexte limité unique, envisagez plutôt un modèle d’orchestrateur, en fonction de la complexité et de la préférence de l’équipe.
L’orchestrateur central introduit un goulot d’étranglement des performances.
Ce modèle peut ne pas convenir lorsque :
L’application est complexe et nécessite un composant central capable de gérer une logique partagée afin de préserver la légèreté des composants en aval.
La communication point à point entre les composants est inévitable.
Vous devez utiliser la logique métier pour consolider toutes les opérations gérées par les composants en aval.
Conception de la charge de travail
Évaluez comment utiliser le modèle de chorégraphie dans la conception d'une charge de travail pour répondre aux objectifs et principes abordés dans les piliers du cadre Azure Well-Architected Framework. Le tableau suivant fournit des conseils sur la façon dont ce modèle prend en charge les objectifs de chaque pilier.
| 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 de l’équipe. | Les composants distribués de ce modèle sont autonomes et conçus pour être remplaçables. Vous pouvez donc modifier la charge de travail avec moins de modification globale du système. - OE :04 Outils et processus |
| L’efficacité des performances permet à votre charge de travail de répondre efficacement aux demandes par le biais d’optimisations de la mise à l’échelle, des données et 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 chorégraphique en créant une charge de travail native cloud basée sur des événements qui s’exécute en même temps que des microservices. Lorsqu’un client demande d’expédier un package, la charge de travail affecte un drone. Une fois le colis prêt à être récupéré par le drone planifié, le processus de livraison commence. Pendant que le colis est en transit, le flux de travail gère la livraison jusqu'à ce qu'il atteigne le statut 'expédié'. Pour obtenir l’architecture de référence complète, consultez Microservices avec Azure Container Apps.
Le service d’ingestion reçoit les demandes du client et les convertit en messages qui incluent les détails de remise. Les transactions commerciales commencent après que les services consomment ces nouveaux messages.
Une transaction commerciale pour un cliente unique requiert trois opérations commerciales distinctes :
Créez ou mettez à jour un package.
Attribuez un drone pour livrer le colis.
Gérez la livraison, y compris la vérification et l’envoi d’une notification lorsque le colis est livré.
Les microservices Colis, Planification des drones et Livraison effectuent le traitement des activités. Les services utilisent la messagerie au lieu d’un orchestrateur central pour communiquer entre eux. Chaque service doit implémenter un protocole à l’avance qui coordonne le flux de travail d’entreprise de manière décentralisée.
Conception
Les services traitent les transactions métier dans une séquence via plusieurs étapes. Chaque tronçon partage un seul bus de messages entre tous les services d’entreprise.
Lorsqu’un client envoie une demande de remise via un point de terminaison HTTP, le service d’ingestion le reçoit, le convertit en message, puis publie le message dans le bus de messages partagé. Les services commerciaux abonnés consomment les nouveaux messages ajoutés au bus. Lorsqu’un service d’entreprise reçoit le message, il termine l’opération correctement, ou la demande échoue ou expire. Si la requête réussit, le service répond au bus avec le Ok code d’état, déclenche un nouveau message d’opération et l’envoie au bus de messages. Si la demande échoue ou dépasse le délai imparti, le service transmet le code de raison de l’échec sur le bus de messages et place le message dans la file d'attente de lettres par l'intermédiaire d'Azure Service Bus. Le service met également en file d'attente de lettres mortes des messages qu’il ne peut pas recevoir ou traiter dans un délai spécifique.
Cette conception utilise plusieurs bus de messages pour traiter l’ensemble de la transaction métier. Azure Service Bus et Azure Event Grid fournissent la plateforme de service de messagerie pour cette conception. La charge de travail s’exécute sur Azure Container Apps. Le service d’ingestion s’exécute en tant que fonction Azure hébergée sur Container Apps, tandis que le package, le planificateur de drones et les services de livraison s’exécutent en tant que microservices dans le même environnement Container Apps. Container Apps gère le traitement piloté par les événements qui exécute la logique métier.
Cette conception garantit également que la chorégraphie se produit dans une séquence. Un espace de noms Service Bus unique contient une rubrique qui comporte deux abonnements et une file d’attente prenant en compte les sessions. Le service d’ingestion publie des messages dans la rubrique. Les services de colis et de planification de drone s’abonnent à la rubrique et publient des messages qui informent la file d’attente des demandes réussies. Incluez un identificateur de session commun qui associe un GUID à l’identificateur de remise afin que le service de remise puisse mettre en corrélation les deux messages dont il a besoin pour chaque transaction. Un message confirme que le package est prêt, l’autre message confirme qu’un drone est planifié. Sans cette corrélation basée sur une session, le service de remise n’a aucun moyen d’associer des messages connexes entre des tronçons indépendants, car aucun coordinateur central n’effectue le suivi de l’état des transactions. Le service de remise attend deux messages associés pour chaque transaction. Le premier message indique que le package est prêt à être expédié, et le deuxième message signale qu’un drone est planifié.
Dans cette conception, Service Bus gère les messages à valeur élevée qui ne doivent pas être perdus ou dupliqués pendant l’ensemble du processus de remise. Lorsque le package est livré, un changement d’état est publié sur Event Grid. 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 que cette conception n’inclut pas peuvent écouter ce type d’événement et exécuter une logique métier spécifique, comme l’envoi d’un e-mail d’état de commande à l’utilisateur.
Si vous déployez ce modèle dans un autre service de calcul, tel qu’AKS, vous pouvez déployer un ambassadeur en tant que side-car dans le même pod que l’application métier. La colocalisation minimise la latence de communication, mais le proxy ajoute une surcharge de traitement et de consommation de ressources, et augmente avec l’application. Utilisez cette approche lorsque vous avez besoin de problèmes de connectivité indépendants du langage que la plateforme ne fournit pas.
Pour éviter les opérations de nouvelle tentative en cascade susceptibles d’entraîner plusieurs tentatives, les services d’entreprise doivent immédiatement marquer des messages inacceptables. Enrichissez ces messages à l’aide de codes de raison courants ou d’un code d’application défini afin que les services puissent les déplacer vers une DLQ. Envisagez d’implémenter le modèle Saga pour gérer les problèmes de cohérence des services en aval. Par exemple, un autre service traite les messages en lettres mortes à des fins de remédiation uniquement en exécutant une transaction de compensation, de nouvelle tentative ou de pivot.
Les services métier sont idempotents pour s’assurer que les opérations de nouvelle tentative ne créent pas de ressources en double. Par exemple, le service de paquet utilise des opérations upsert pour ajouter des données au stockage de données.
Étape suivante
- Passez en revue les options de messagerie asynchrone dans Azure pour en savoir plus sur les différents choix d’infrastructure disponibles pour implémenter un flux de travail décentralisé.
Ressources associées
Tenez compte de ces motifs dans votre conception pour la chorégraphie :
Utilisez le modèle Ambassadeur pour modulariser la communication des services d’entreprise avec le bus de messages.
Implémentez le modèle d'équilibrage de charge basé sur la file d'attente pour gérer les pics de charge de travail.
Utilisez la messagerie distribuée asynchrone par le biais du modèle Publisher-Subscriber.
Utilisez des transactions de compensation pour annuler une série d’opérations réussies si une ou plusieurs opérations associées échouent.