Partager via


Accès concurrentiel dans Azure Functions

Cet article décrit les comportements d’accès concurrentiel des déclencheurs pilotés par les événements dans Azure Functions. Le système compare également les modèles de concurrence statique et dynamique.

Important

Le plan Consommation flexible est actuellement en préversion.

Dans Functions, vous pouvez avoir plusieurs processus d’exécution d’une fonction donnée s’exécutant simultanément sur une seule instance de calcul. Par exemple, prenons un cas où vous avez trois fonctions différentes dans votre application de fonction, qui effectue un scale-out sur plusieurs instances pour gérer une charge accrue. Dans ce scénario, chaque fonction s’exécute en réponse à des appels individuels sur les trois instances et une instance donnée peut gérer plusieurs appels du même type. Rappelez-vous que les exécutions de fonction sur une instance unique partagent la même mémoire, le même processeur et les mêmes ressources de connexion. Étant donné que plusieurs fonctions peuvent s’exécuter simultanément sur chaque instance, chaque fonction doit avoir un moyen de gérer le nombre d’exécutions simultanées.

Lorsque votre application est hébergée dans un plan de mise à l'échelle dynamique (Consommation, Consommation flexible ou Premium), l’hôte met à l’échelle (scale-up ou scale-down) le nombre d’instances de l’application de fonction en fonction du nombre d’événements entrants. Si vous souhaitez en savoir plus, veuillez consulter la rubrique Mise à l’échelle pilotée par les événements. Lorsque vous hébergez vos fonctions dans un plan Dedicated (App Service), vous devez configurer manuellement vos instances ou configurez un schéma de mise à l’échelle automatique.

Ces décisions de mise à l’échelle sont également directement affectées par la concurrence des exécutions sur une instance donnée. Lorsqu’une application d’un plan de mise à l’échelle dynamique atteint une limite d’accès concurrentiel, une mise à l’échelle peut être nécessaire pour suivre la demande entrante.

Functions fournit deux méthodes principales de gestion de la concurrence :

  • Concurrence statique : vous pouvez configurer des limites au niveau de l’hôte sur la concurrence, qui sont spécifiques aux déclencheurs individuels. Il s’agit du comportement de la concurrence par défaut pour Functions.

  • Concurrence dynamique : pour certains types de déclencheurs, l’hôte Functions peut déterminer automatiquement le meilleur niveau de concurrence pour ce déclencheur dans votre application. Vous devez choisir ce modèle de concurrence.

Concurrence statique

Par défaut, la plupart des déclencheurs prennent en charge un modèle de configuration statique au niveau de l’hôte. Dans ce modèle, chaque type de déclencheur a une limite de concurrence par instance. Toutefois, pour la plupart des déclencheurs, vous pouvez également demander une concurrence par instance spécifique pour ce type de déclencheur en question. Par exemple, le déclencheur Service Bus fournit des paramètres MaxConcurrentCalls et MaxConcurrentSessions dans le fichier host.json. Ces paramètres contrôlent ensemble le nombre maximal de messages que chaque fonction traite simultanément sur chaque instance. D’autres types de déclencheurs intègrent des mécanismes pour les appels d’équilibrage de charge entre les instances. Par exemple, Event Hubs et Azure Cosmos DB utilisent tous les deux un schéma basé sur les partitions.

Pour les types de déclencheurs qui prennent en charge la configuration de la concurrence, les paramètres que vous choisissez s’appliquent à toutes les instances en cours d’exécution. Cela vous permet de contrôler la concurrence maximale pour vos fonctions sur chaque instance. Par exemple, lorsque votre fonction est gourmande en processeur ou en ressources, vous pouvez choisir de limiter la concurrence pour assurer l’intégrité des instances et compter sur la mise à l’échelle pour gérer les charges accrues. De même, lorsque votre fonction effectue des requêtes auprès d’un service en aval qui est limité, nous vous recommandons également de limiter la concurrence pour éviter la surcharge du service en aval.

Concurrence du déclencheur HTTP

Applicable uniquement au plan Consommation flexible (préversion)

Le plan Consommation flexible met à l’échelle toutes les fonctions de déclencheur HTTP ensemble en tant que groupe. Si vous souhaitez en savoir plus, veuillez consulter la rubrique Mise à l’échelle par fonction. Le tableau suivant indique le paramètre de concurrence par défaut pour les déclencheurs HTTP sur une instance donnée, en fonction de la taille de mémoire de l’instance configurée.

Taille de l’instance (Mo) Concurrence par défaut*
2048 16
4096 32

*Pour les applications Python, la concurrence de déclencheur HTTP par défaut pour toutes les tailles d’instances est 1.

Ces valeurs par défaut doivent fonctionner correctement pour la plupart des cas. Ensuite, commencez par les utiliser. N’oubliez pas qu’à un nombre donné de requêtes HTTP, l’augmentation de la valeur de concurrence HTTP réduit le nombre d’instances requises pour gérer les requêtes HTTP. De même, la diminution de la valeur de concurrence HTTP nécessite davantage d’instances pour gérer la même charge.

Si vous devez affiner la concurrence HTTP, vous pouvez utiliser Azure CLI. Si vous souhaitez en savoir plus, veuillez consulter la rubrique Définir les limites de concurrence HTTP.

Les valeurs de concurrence par défaut dans le tableau précédent s’appliquent uniquement lorsque vous n’avez pas défini votre propre paramètre de concurrence HTTP. Lorsque vous n’avez pas défini explicitement de paramètre de concurrence HTTP, la concurrence par défaut augmente, comme indiqué dans le tableau lorsque vous modifiez la taille de l’instance. Une fois que vous avez défini spécifiquement une valeur de concurrence HTTP, cette valeur est conservée malgré les modifications du paramètre de la taille d’instance.

Déterminer la concurrence statique optimale

Bien que les configurations de concurrence statique vous permettent de contrôler certains comportements de déclencheur, comme la limitation de vos fonctions, il peut être difficile de déterminer les valeurs optimales pour ces paramètres. En règle générale, vous devez obtenir des valeurs acceptables par un processus itératif de test de charge. Même après que vous avez déterminé un ensemble de valeurs qui fonctionnent pour un profil de charge particulier, le nombre d’événements arrivant de vos services connectés peut changer d’un jour à l’autre. Cette variabilité signifie que votre application peut souvent s’exécuter avec des valeurs non optimales. Par exemple, votre application de fonction peut traiter des charges utiles de messages particulièrement exigeantes le dernier jour de la semaine, ce qui vous oblige à limiter la concurrence. Toutefois, pendant le reste de la semaine, les charges utiles de message sont plus simples, ce qui signifie que vous pouvez utiliser un niveau de concurrence plus élevé.

Dans l’idéal, nous voulons que le système autorise les instances à traiter autant de travail qu’elles le permettent, tout en maintenant l’intégrité et les latences de chaque instance, ce pour quoi l’accès concurrentiel dynamique est conçu.

Concurrence dynamique

Functions fournit désormais un modèle de concurrence dynamique qui simplifie la configuration de l’accès concurrentiel pour toutes les applications de fonction s’exécutant dans le même plan.

Notes

L’accès concurrentiel dynamique n’est actuellement pris en charge que pour les déclencheurs de Blob Azure, de File d’attente Azure et de Service Bus. Il exige que vous utilisiez les versions répertoriées dans la section relative à la prise en charge des extensions ci-dessous.

Avantages

L’utilisation de la concurrence dynamique offre les avantages suivants :

  • Configuration simplifiée : vous n’avez plus besoin de déterminer manuellement les paramètres de concurrence par déclenchement. Le système apprend les valeurs optimales pour votre charge de travail au fil du temps.
  • Ajustements dynamiques : l’accès concurrentiel est ajusté dynamiquement en temps réel, ce qui permet au système de s’adapter à la modification des modèles de charge dans le temps.
  • Protection d’intégrité de l’instance : le runtime limite l’accès concurrentiel à des niveaux qu’une instance d’application de fonction peut gérer confortablement. Cela empêche l’application de se surcharger elle-même en prenant plus de travail qu’elle ne le devrait.
  • Débit amélioré : le débit global est amélioré, car les instances individuelles ne prennent pas plus de travail qu’elles ne peuvent traiter rapidement. Cela permet d’équilibrer la charge de travail de façon plus efficace entre les instances. Pour les fonctions qui peuvent gérer des charges plus élevées, vous pouvez obtenir un débit plus élevé en augmentant la concurrence pour les valeurs au-dessus de la configuration par défaut.

Configuration de la concurrence dynamique

L’accès concurrentiel dynamique peut être activé au niveau de l’hôte dans le fichier host.json. Lorsque cette fonction est activée, les niveaux de concurrence de toutes les extensions de liaison qui prennent en charge cette fonctionnalité sont ajustés automatiquement en fonction des besoins. Dans ces cas, les paramètres de concurrence dynamique remplacent tous les paramètres de concurrence configurés manuellement.

Par défaut, la concurrence dynamique est désactivée. Avec la concurrence dynamique activée, la concurrence commence à 1 pour chaque fonction et est ajustée à une valeur optimale, qui est déterminée par l’hôte.

Vous pouvez activer l’accès concurrentiel dynamique dans votre application de fonction en ajoutant les paramètres suivants dans votre fichier host.json :

    { 
        "version": "2.0", 
        "concurrency": { 
            "dynamicConcurrencyEnabled": true, 
            "snapshotPersistenceEnabled": true 
        } 
    } 

Quand SnapshotPersistenceEnabled est true, ce qui correspond à la valeur par défaut, les valeurs d’accès concurrentiel apprises sont régulièrement conservées dans le stockage. Par conséquent, les nouvelles instances commencent à partir de ces valeurs au lieu de commencer à partir de 1 et de recommencer l’apprentissage.

Gestionnaire d’accès concurrentiel

En arrière-plan, lorsque l’accès concurrentiel dynamique est activé, un processus de gestionnaire d’accès concurrentiel s’exécute en arrière-plan. Ce gestionnaire surveille en permanence les mesures d’intégrité de l’instance, comme l’utilisation du processeur et des threads, et modifie les limitations en fonction des besoins. Quand une ou plusieurs limitations sont activées, la concurrence des fonctions est ajustée jusqu’à ce que l’hôte soit de nouveau sain. Lorsque les limitations sont désactivées, la concurrence est autorisée à augmenter. Diverses méthodes heuristiques sont utilisées pour ajuster intelligemment la concurrence en fonction des besoins selon ces limitations. Au fil du temps, la concurrence pour chaque fonction se stabilise à un niveau particulier.

Les niveaux de concurrence sont gérés pour chaque fonction individuelle. Par conséquent, le système équilibre les fonctions gourmandes en ressources qui requièrent un faible niveau de simultanéité et les fonctions plus légères qui peuvent gérer une concurrence plus élevée. L’équilibre de la concurrence pour chaque fonction permet de maintenir l’intégrité globale de l’instance d’application de fonction.

Lorsque l’accès concurrentiel dynamique est activé, vous verrez les décisions de concurrence dynamique dans vos journaux. Par exemple, vous verrez des journaux lorsque différentes limitations sont activées et chaque fois que la concurrence est ajustée à la hausse ou à la baisse pour chaque fonction. Ces journaux sont écrits sous la catégorie Host.Concurrency dans la table des traces.

Extensions prises en charge

La concurrence dynamique est activée pour une application de fonction au niveau de l’hôte, et toutes les extensions qui prennent en charge la concurrence dynamique s’exécutent dans ce mode. La concurrence dynamique nécessite une collaboration entre l’hôte et les extensions de déclencheur individuelles. Seules les versions listées des extensions suivantes prennent en charge la concurrence dynamique.

Extension Version Description
Stockage File d’attente version 5.x (extension du Stockage) Le déclencheur stockage de File d’attente Azure possède sa propre boucle d’interrogation des messages. Lors de l’utilisation d’une configuration statique, la concurrence est régie par les options de configuration BatchSize/NewBatchThreshold. Lorsque vous utilisez un accès concurrentiel dynamique, ces valeurs de configuration sont ignorées. L’accès concurrentiel dynamique étant intégré à la boucle de messages, le nombre de messages extraits par itération est ajusté de manière dynamique. Lorsque des limitations sont activées (l’hôte est surchargé), le traitement des messages est suspendu jusqu’à ce que les limitations soient désactivées. Lorsque les limitations sont désactivées, la concurrence augmente.
Stockage Blob version 5.x (extension du Stockage) En interne, le déclencheur stockage Blob Azure utilise la même infrastructure que le déclencheur de File d’attente Azure. Lorsque des blobs nouveaux ou mis à jour doivent être traités, les messages sont écrits dans une file d’attente de contrôle managée de la plateforme, et la file d’attente est traitée à l’aide de la même logique que celle utilisée pour le déclencheur de File d’attente. Lorsque la concurrence dynamique est activée, la concurrence pour le traitement de cette file d’attente de contrôle est gérée de façon dynamique.
Service Bus version 5.x Le déclencheur Service Bus prend actuellement en charge trois modèles d’exécution. La concurrence dynamique affecte ces modèles d’exécution comme suit :

Traitement de la rubrique/file d’attente à distribution unique : chaque appel de votre fonction traite un message unique. Lors de l’utilisation d’une configuration statique, la concurrence est régie par l’option de configuration MaxConcurrentCalls. Lors de l’utilisation de la concurrence dynamique, cette valeur de configuration est ignorée et la concurrence est ajustée dynamiquement.
Traitement de la rubrique/file d’attente à distribution unique basée sur la session : chaque appel de votre fonction traite un message unique. En fonction du nombre de sessions actives pour votre rubrique/file d’attente, chaque instance loue une ou plusieurs sessions. Les messages de chaque session sont traités en série, afin de garantir l’ordre dans une session. Lorsque la concurrence dynamique n’est pas utilisée, la concurrence est régie par le paramètre MaxConcurrentSessions. Avec la concurrence dynamique activée, MaxConcurrentSessions est ignoré et le nombre de sessions que chaque instance traite est ajusté dynamiquement.
Traitement par lots : chaque appel de votre fonction traite un lot de messages, régi par le paramètre MaxMessageCount. Étant donné que les appels de lot sont en série, la concurrence pour votre fonction déclenchée par lot est toujours 1 et la concurrence dynamique ne s’applique pas.

Étapes suivantes

Pour plus d’informations, consultez les ressources suivantes :