Partager via


Orchestrations durables

Durable Functions est une extension d’Azure Functions qui permet d’exécuter des fonctions avec état dans un environnement de calcul serverless. Dans une application de fonction durable, vous pouvez utiliser une fonction d’orchestrateur pour orchestrer l’exécution d’autres fonctions durables. Les fonctions Orchestrator présentent les caractéristiques suivantes :

  • Ils définissent des flux de travail de fonction à l’aide du code procédural. Aucun schéma déclaratif ni concepteur n’est nécessaire.
  • Ils peuvent appeler d’autres fonctions durables de manière synchrone et asynchrone. La sortie des fonctions appelées peut être enregistrée dans des variables locales.
  • Ils sont conçus pour être durables et fiables. La progression de l’exécution est automatiquement enregistrée en tant que point de contrôle lorsque la fonction appelle un opérateur await ou yield. L’état local n’est pas perdu lorsque le processus recycle ou que la machine virtuelle redémarre.
  • Ils peuvent durer longtemps. La durée de vie totale d’une instance d’orchestration peut être de secondes, de jours ou de mois, ou l’instance peut être configurée pour ne jamais se terminer.

Cet article vous donne une vue d’ensemble des fonctions d’orchestrateur et explique comment elles peuvent vous aider à résoudre différents problèmes de développement d’applications. Pour plus d’informations sur les types de fonctions disponibles dans une application Durable Functions, consultez les types et fonctionnalités Durable Functions.

Identité d’orchestration

Chaque instance d’une orchestration a un identificateur d’instance, également appelé ID d’instance. Par défaut, chaque ID d’instance est un identificateur global unique généré automatiquement. Toutefois, les ID d’instance peuvent également être n’importe quelle valeur de chaîne générée par l’utilisateur. Chaque ID d’instance d’orchestration doit être unique dans un hub de tâches.

Les règles suivantes s’appliquent aux ID d’instance :

  • Elles doivent être comprises entre 1 et 100 caractères.
  • Ils ne doivent pas commencer par @.
  • Ils ne doivent pas contenir /, , \#ou ? caractères.
  • Ils ne doivent pas contenir de caractères de contrôle.

Note

Nous vous recommandons généralement d’utiliser des ID d’instance générés automatiquement chaque fois que cela est possible. Les ID d’instance générés par l’utilisateur sont destinés aux scénarios où il existe un mappage un-à-un entre une instance d’orchestration et une entité externe spécifique à l’application, comme un bon de commande ou un document.

En outre, l’application réelle des règles de restriction de caractères peut varier en fonction du fournisseur de stockage que l’application utilise. Pour garantir un comportement et une compatibilité corrects, nous vous recommandons vivement de suivre les règles d’ID d’instance précédentes.

L’ID d’instance d’une orchestration est un paramètre requis pour la plupart des opérations de gestion d’instance. Les ID d’instance sont également importants pour les diagnostics. Par exemple, vous les utilisez lorsque vous effectuez une recherche dans des données de suivi d’orchestration dans Application Insights à des fins de résolution des problèmes ou d’analytique. Pour cette raison, nous vous recommandons d’enregistrer les ID d’instance générés dans un emplacement externe qui facilite leur référence ultérieurement. Des exemples d’emplacements incluent des bases de données ou des logs d'applications.

Reliability

Les fonctions d’Orchestrator utilisent le modèle d’approvisionnement d’événements pour les aider à maintenir un état d’exécution fiable. Au lieu de stocker directement l’état actuel d’une orchestration, le framework Durable Task utilise un magasin d’ajout uniquement pour enregistrer toute la série d’actions effectuées par l’orchestration de fonction. Un magasin d’ajout seul présente de nombreux avantages par rapport au vidage de l’état d’exécution complet. Les avantages incluent une amélioration des performances, de la scalabilité et de la réactivité. Vous bénéficiez aussi d'une cohérence à terme pour les données transactionnelles, ainsi que de pistes d’audit complètes et de l’historique. Les pistes d’audit prennent en charge des actions de compensation fiables.

Durable Functions utilise l’approvisionnement en événements de manière transparente. En arrière-plan, une fonction d’orchestrateur utilise un await opérateur en C# et un yield opérateur en JavaScript et Python. Ces opérateurs renvoient le contrôle du thread orchestrateur au répartiteur d’infrastructure de tâches durables. Dans les fonctions Java, il n’existe aucun mot clé de langage spécial. Au lieu de cela, l’appel de .await() à une tâche renvoie le contrôle au répartiteur via une instance personnalisée de Throwable. Le répartiteur envoie ensuite toutes les nouvelles actions planifiées par la fonction d’orchestrateur dans la mémoire de stockage. Parmi les exemples d’actions, il existe l’appel d’une ou de plusieurs fonctions enfants ou la planification d’un minuteur durable. L’action de validation transparente met à jour l’historique d’exécution de l’instance d’orchestration en ajoutant tous les nouveaux événements au stockage, comme dans le cas d’un journal d’ajout uniquement. De même, l’action de validation crée des messages dans le stockage pour planifier le travail réel. À ce stade, la fonction d’orchestrateur peut être déchargée de la mémoire. Par défaut, Durable Functions utilise stockage Azure comme magasin d’état d’exécution, mais d’autres fournisseurs de stockage sont également pris en charge.

Lorsqu’une fonction d’orchestration est donnée plus de travail à effectuer (par exemple, un message de réponse est reçu ou un minuteur durable expire), l’orchestrateur se réveille et réexécute la fonction entière à partir du début pour reconstruire l’état local. Pendant la relecture, si le code tente d’appeler une fonction (ou d’effectuer tout autre travail asynchrone), le Durable Task Framework consulte l’historique d’exécution de l’orchestration actuelle. Si elle constate que la fonction d’activité a déjà été exécutée et a généré un résultat, elle relecture le résultat de cette fonction et le code d’orchestrateur continue à s’exécuter. La réexécution se poursuit jusqu’à ce que le code de la fonction soit terminé ou jusqu’à ce qu’il planifie une nouvelle tâche asynchrone.

Note

Pour aider le modèle de relecture à fonctionner correctement et de manière fiable, le code de fonction d’orchestrateur doit être déterministe. Le code d’orchestrateur non déterministe peut entraîner des erreurs d’exécution ou un autre comportement inattendu. Pour plus d’informations sur les restrictions de code pour les fonctions d’orchestrateur, consultez contraintes de code de fonction Orchestrator.

Note

Si une fonction d’orchestrateur émet des messages de journal, le comportement de relecture peut provoquer l’émission de messages de journal en double. Pour plus d’informations sur la raison pour laquelle ce comportement se produit et comment le contourner, consultez journalisation des applications.

Historique de l’orchestration

Le comportement d’approvisionnement en événements de Durable Task Framework est étroitement associé au code de fonction orchestrator que vous écrivez. Supposons que vous disposez d’une fonction d’orchestrateur de chaînage d’activités, comme la fonction d’orchestrateur suivante.

Note

La version 4 du modèle de programmation Node.js pour Azure Functions est généralement disponible. Le modèle v4 est conçu pour offrir une expérience plus flexible et intuitive pour les développeurs JavaScript et TypeScript. Pour plus d’informations sur les différences entre v3 et v4, consultez le guide de migration.

Dans les extraits de code suivants, JavaScript (PM4) désigne le modèle de programmation v4, la nouvelle expérience.

[FunctionName("HelloCities")]
public static async Task<List<string>> Run(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var outputs = new List<string>();

    outputs.Add(await context.CallActivityAsync<string>("SayHello", "Tokyo"));
    outputs.Add(await context.CallActivityAsync<string>("SayHello", "Seattle"));
    outputs.Add(await context.CallActivityAsync<string>("SayHello", "London"));

    // Return ["Hello Tokyo!", "Hello Seattle!", "Hello London!"].
    return outputs;
}

Chaque fois qu’une fonction d’activité est planifiée, Durable Task Framework enregistre l’état d’exécution de la fonction à différents points de contrôle. À chaque point de contrôle, le cadre enregistre l'état dans un back-end de stockage durable, qui est, par défaut, le Azure Table Storage. Cet état est appelé historique d’orchestration.

Table d’historique

En règle générale, le Framework des tâches durables effectue les opérations suivantes à chaque point de contrôle :

  • Enregistre l’historique d’exécution dans un stockage durable.
  • Met en file d’attente les messages pour les fonctions que l’orchestrateur souhaite appeler.
  • Il empile les messages pour l’orchestrateur lui-même, comme des messages d’un minuteur durable.

Une fois le point de contrôle terminé, la fonction d’orchestrateur est libre d’être supprimée de la mémoire jusqu’à ce qu’il y ait plus de travail à effectuer.

Note

Stockage Azure ne fournit aucune garantie transactionnelle concernant la cohérence des données entre le stockage de tables et les files d’attente lorsque les données sont enregistrées. Pour gérer les défaillances, le fournisseur de stockage Azure Durable Functions utilise des modèles de cohérence éventuels . Ces modèles permettent de s’assurer qu’aucune donnée n’est perdue en cas de blocage ou de perte de connectivité au milieu d’un point de contrôle. D’autres fournisseurs de stockage, tels que le fournisseur de stockage Microsoft SQL Server (MSSQL) Durable Functions, peuvent fournir des garanties de cohérence plus fortes.

Lorsque la fonction affichée précédemment se termine, son historique ressemble aux données du tableau suivant dans le stockage table. Les entrées sont abrégées à des fins d’illustration.

PartitionKey (InstanceId) EventType Timestamp Input Nom Résultat Statut
eaee885b Démarrage de l'exécution 2021-05-05T18:45:28.852Z zéro HelloCities
eaee885b OrchestratorStarted 2021-05-05T18:45:32.362Z
eaee885b TâcheProgrammée 2021-05-05T18:45:32.670Z SayHello
eaee885b OrchestratorCompleted 2021-05-05T18:45:32.670Z
eaee885b TaskCompleted 2021-05-05T18:45:34.201Z « "Hello Tokyo !"" »
eaee885b OrchestratorStarted 2021-05-05T18:45:34.232Z
eaee885b TâcheProgrammée 2021-05-05T18:45:34.435Z SayHello
eaee885b OrchestratorCompleted 2021-05-05T18:45:34.435Z
eaee885b TaskCompleted 2021-05-05T18:45:34.763Z « ""Hello Seattle !"" »
eaee885b OrchestratorStarted 2021-05-05T18:45:34.857Z
eaee885b TâcheProgrammée 2021-05-05T18:45:34.857Z SayHello
eaee885b OrchestratorCompleted 2021-05-05T18:45:34.857Z
eaee885b TaskCompleted 2021-05-05T18:45:34.919Z « "Hello London !"" »
eaee885b OrchestratorStarted 2021-05-05T18:45:35.032Z
eaee885b OrchestratorCompleted 2021-05-05T18:45:35.044Z
eaee885b Exécution terminée 2021-05-05T18:45:35.044Z « ["Hello Tokyo !" »,"Hello Seattle !" »,"Hello London !""] » Terminé

Les colonnes de table contiennent les valeurs suivantes :

  • PartitionKey : ID d’instance de l’orchestration.
  • EventType : type de l’événement. Pour obtenir des descriptions détaillées de tous les types d’événements d’historique, consultez Événements d’historique de l’infrastructure de tâches durables.
  • Horodatage : l'Horodatage universel coordonné de l'événement historique.
  • Entrée : entrée au format JSON de la fonction.
  • Nom : nom de la fonction appelée.
  • Résultat : sortie de la fonction, en particulier, sa valeur de retour.

Avertissement

Ce tableau peut être utile en tant qu’outil de débogage. Mais gardez à l’esprit que son format et son contenu peuvent changer à mesure que l’extension Durable Functions évolue.

Chaque fois que la fonction est reprise après avoir attendu la fin d'une tâche, le Framework de tâches durables réexécute la fonction d'orchestration depuis le début. Sur chaque réexécution, il consulte l’historique d’exécution pour déterminer si la tâche asynchrone actuelle est terminée. Si l’historique d’exécution indique que la tâche est déjà terminée, l’infrastructure relit la sortie de cette tâche et passe à la tâche suivante. Ce processus se poursuit jusqu’à ce que l’intégralité de l’historique d’exécution ait été relue. Dès que l’historique d’exécution actuel a été relu, les variables locales sont restaurées à leurs valeurs précédentes.

Fonctionnalités et modèles

Les sections suivantes décrivent les fonctionnalités et les modèles des fonctions d’orchestrateur.

Sous-orchestrations

Les fonctions Orchestrator peuvent appeler des fonctions d’activité, mais également d’autres fonctions d’orchestrateur. Par exemple, vous pouvez créer une orchestration plus grande à partir d’une bibliothèque de fonctions d’orchestrateur. Vous pouvez également exécuter plusieurs instances d’une fonction d’orchestrateur en parallèle.

Pour plus d’informations et pour obtenir des exemples, consultez Sous-orchestrations dans Durable Functions (Azure Functions).

Temporisateurs durables

Les orchestrations peuvent planifier des minuteurs durables pour implémenter des retards ou configurer le traitement des délais d’expiration sur les actions asynchrones. Utilisez des minuteurs durables dans les fonctions d’orchestrateur au lieu des API natives sleep du langage.

Pour plus d’informations et pour obtenir des exemples, consultez Timers in Durable Functions (Azure Functions).

Événements externes

Les fonctions Orchestrator peuvent attendre que des événements externes mettent à jour une instance d’orchestration. Cette fonctionnalité Durable Functions est souvent utile pour gérer les interactions humaines ou d’autres rappels externes.

Pour plus d’informations et pour obtenir des exemples, consultez Gestion des événements externes dans Durable Functions (Azure Functions).

Gestion des erreurs

Les fonctions Orchestrator peuvent utiliser les fonctionnalités de gestion des erreurs du langage de programmation. Les modèles existants comme ceux-ci try/catch sont pris en charge dans le code d’orchestration.

Les fonctions orchestrator peuvent également ajouter des stratégies de nouvelles tentatives à l’activité ou aux fonctions orchestrator secondaires qu’elles appellent. Si une fonction d’activité ou de sous-orchestrateur échoue avec une exception, la stratégie de nouvelle tentative spécifiée peut retarder et réessayer automatiquement l’exécution jusqu’à un nombre spécifié de fois.

Note

S’il existe une exception non gérée dans une fonction d’orchestrateur, l’instance d’orchestration se termine dans un Failed état. Une instance d’orchestration ne peut pas être retentée une fois qu’elle a échoué.

Pour plus d’informations et pour obtenir des exemples, consultez Gestion des erreurs dans Durable Functions (Azure Functions).

Sections critiques (Durable Functions 2.x, actuellement .NET uniquement)

Les instances d’orchestration sont monothreads, de sorte que les conditions de concurrence ne sont pas un problème au sein d’une orchestration. Toutefois, des conditions de compétition peuvent se produire lorsque les orchestrations interagissent avec des systèmes externes. Pour atténuer les conditions de concurrence lors de l’interaction avec des systèmes externes, les fonctions d’orchestrateur peuvent définir des sections critiques à l’aide d’une LockAsync méthode dans .NET.

L’exemple de code suivant montre une fonction d’orchestrateur qui définit une section critique. Il utilise la LockAsync méthode pour entrer la section critique. Cette méthode nécessite de passer une ou plusieurs références à une entité durable, qui gère durablement l’état de verrouillage. Une seule instance de cette orchestration peut exécuter le code dans la section critique à la fois.

[FunctionName("Synchronize")]
public static async Task Synchronize(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    var lockId = new EntityId("LockEntity", "MyLockIdentifier");
    using (await context.LockAsync(lockId))
    {
        // Critical section. Only one orchestration can enter at a time.
    }
}

La méthode LockAsync acquiert les verrous durables et retourne un IDisposable qui met fin à la section critique quand elle est supprimée. Ce IDisposable résultat peut être utilisé avec un using bloc pour obtenir une représentation syntaxique de la section critique. Lorsqu’une fonction d’orchestrateur entre une section critique, une seule instance peut exécuter ce bloc de code. Toutes les autres instances qui tentent d’entrer la section critique sont bloquées jusqu’à ce que l’instance précédente quitte la section critique.

La fonctionnalité de section critique est également utile pour coordonner les modifications apportées aux entités durables. Pour plus d’informations sur les sections critiques, consultez Coordination des entités.

Note

Les sections critiques sont disponibles dans Durable Functions 2.0. Actuellement, seules les orchestrations in-process .NET implémentent cette fonctionnalité. Les entités et les sections critiques ne sont pas encore disponibles dans Durable Functions pour les orchestrations de travail isolées .NET.

Appels aux points de terminaison HTTP (Durable Functions 2.x)

Les fonctions Orchestrator ne sont pas autorisées à effectuer des opérations d’E/S, comme décrit dans les contraintes de code de fonction Orchestrator. La solution de contournement classique pour cette limitation consiste à encapsuler tout code qui doit effectuer des opérations d’E/S dans une fonction d’activité. Les orchestrations qui interagissent avec des systèmes externes utilisent fréquemment des fonctions d’activité pour effectuer des appels HTTP et retourner les résultats à l’orchestration.

Pour simplifier ce modèle commun, les fonctions d’orchestrateur peuvent utiliser la CallHttpAsync méthode pour appeler directement des API HTTP.

[FunctionName("CheckSiteAvailable")]
public static async Task CheckSiteAvailable(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    Uri url = context.GetInput<Uri>();

    // Make an HTTP GET request to the specified endpoint.
    DurableHttpResponse response = 
        await context.CallHttpAsync(HttpMethod.Get, url);

    if ((int)response.StatusCode == 400)
    {
        // Handle error codes.
    }
}

Outre la prise en charge des modèles de requête/réponse de base, la méthode prend en charge la gestion automatique des modèles d’interrogation HTTP 202 asynchrones courants. Il prend également en charge l’authentification avec des services externes à l’aide d’identités managées.

Pour plus d’informations et pour obtenir des exemples détaillés, consultez les fonctionnalités HTTP.

Note

L’appel de points de terminaison HTTP directement à partir de fonctions d’orchestrateur est disponible dans Durable Functions 2.0 et versions ultérieures.

Paramètres multiples

Il n’est pas possible de passer plusieurs paramètres à une fonction d’activité directement. La recommandation est de passer un tableau d’objets ou d’objets composites.

Dans .NET, vous pouvez également utiliser des objets ValueTuple pour passer plusieurs paramètres. L’exemple suivant utilise les fonctionnalités ValueTuple ajoutées avec C# 7 :

[FunctionName("GetCourseRecommendations")]
public static async Task<object> RunOrchestrator(
    [OrchestrationTrigger] IDurableOrchestrationContext context)
{
    string major = "ComputerScience";
    int universityYear = context.GetInput<int>();

    object courseRecommendations = await context.CallActivityAsync<object>(
        "CourseRecommendations",
        (major, universityYear));
    return courseRecommendations;
}

[FunctionName("CourseRecommendations")]
public static async Task<object> Mapper([ActivityTrigger] IDurableActivityContext inputs)
{
    // Parse the input for the student's major and year in university.
    (string Major, int UniversityYear) studentInfo = inputs.GetInput<(string, int)>();

    // Retrieve and return course recommendations by major and university year.
    return new
    {
        major = studentInfo.Major,
        universityYear = studentInfo.UniversityYear,
        recommendedCourses = new []
        {
            "Introduction to .NET Programming",
            "Introduction to Linux",
            "Becoming an Entrepreneur"
        }
    };
}

Étape suivante