Partager via


Guide pour l’exécution d’Azure Functions C# dans le modèle de worker isolé

Cet article présente l’utilisation d’Azure Functions dans .NET à l’aide du modèle Worker isolé. Ce modèle permet à votre projet de cibler des versions de .NET indépendamment d’autres composants runtime. Pour plus d’informations sur les versions .NET spécifiques prises en charge, consultez Version prise en charge.

Utilisez les liens suivants pour commencer immédiatement à créer des fonctions de modèles Worker isolés .NET.

Bien démarrer Concepts Exemples

Pour découvrir uniquement comment déployer un projet de modèle Worker isolé sur Azure, consultez Déployer sur Azure Functions.

Avantages du modèle Worker isolé

Vous pouvez exécuter vos fonctions de bibliothèque de classes .NET dans deux modes : soit dans le même processus que le runtime hôte Functions (in-process), soit dans un processus Worker isolé. Lorsque vos fonctions .NET sont exécutées dans un processus worker isolé, vous pouvez tirer parti des avantages suivants :

  • Moins de conflits : vos fonctions s’exécutant dans un processus distinct, les assemblys utilisés dans votre application ne sont pas en conflit avec des versions différentes des mêmes assemblys utilisés par le processus hôte.
  • Contrôle total du processus : vous contrôlez le démarrage de l’application, ce qui signifie que vous pouvez gérer les configurations utilisées et l’intergiciel démarré.
  • Injection de dépendances standard : étant donné que vous contrôlez totalement le processus, vous pouvez utiliser les comportements .NET actuels pour injecter des dépendances et incorporer l’intergiciel dans votre application de fonction.
  • Flexibilité de la version .NET : l’exécution en dehors du processus hôte signifie que vos fonctions peuvent s’exécuter sur des versions de .NET non prises en charge en mode natif par le runtime Functions, y compris le .NET Framework.

Si vous avez une application de fonction C# existante qui s’exécute in-process, vous devez migrer votre application pour tirer parti de ces avantages. Pour plus d’informations, consultez Migrer des applications .NET du modèle in-process vers le modèle Worker isolé.

Pour obtenir une comparaison complète des deux modèles, consultez Différences entre les processus .NET in-process et les processus Worker isolés Azure Functions.

Versions prises en charge

Les versions du runtime Functions prend en charge des versions spécifiques de .NET. Pour en savoir plus sur les versions de Functions, consultez Vue d’ensemble des versions du runtime Azure Functions. La prise en charge des versions varie également selon que vos fonctions s’exécutent in-process ou dans des processus Worker isolés.

Notes

Pour savoir comment modifier la version du runtime Functions utilisée par votre application de fonction, consultez Afficher et mettre à jour la version actuelle du runtime.

Le tableau suivant indique le niveau le plus élevé de .NET ou .NET Framework pouvant être utilisé avec une version spécifique de Functions.

Version du runtime Functions Modèle de worker isolé Modèle in-process5
Functions 4.x1 .NET 9.0 (préversion)
.NET 8.0
.NET 6.02
.NET Framework 4.83
.NET 8.0
.NET 6.02
Functions 1.x4 n/a .NET Framework 4.8

1 .NET 7 a été précédemment pris en charge sur le modèle de travail isolé, mais a atteint la fin du support officiel le 14 mai 2024.

2 .NET 6 atteint la fin du support officiel le 12 novembre 2024.

3 Le processus de génération nécessite également le kit de développement logiciel (SDK) .NET.

4 La prise en charge de la version 1.x du runtime Azure Functions prend fin le 14 septembre 2026. Pour plus d’informations, lisez cette annonce relative à la prise en charge. Pour une prise en charge complète continue, vous devez migrer vos applications vers la version 4.x.

5 La prise en charge du modèle in-process prendra fin le 10 novembre 2026. Pour plus d’informations, lisez cette annonce relative à la prise en charge. Pour continuer à bénéficier d’une prise en charge complète, vous devez migrer vos applications vers le modèle worker isolé.

Pour obtenir les dernières informations sur les versions Azure Functions, notamment sur la suppression des versions mineures les plus anciennes, surveillez les annonces Azure App Service.

Structure de projet

Un projet .NET pour Azure Functions utilisant le modèle Worker isolé est essentiellement un projet d’application console .NET qui cible un runtime .NET pris en charge. Voici les fichiers de base requis dans un projet isolé .NET :

  • Fichier projet C# (.csproj) définissant le projet et les dépendances.
  • Fichier Program.cs correspondant au point d’entrée de l’application.
  • Tous les fichiers de code définissant vos fonctions.
  • Fichier host.json qui définit la configuration partagée par les fonctions de votre projet.
  • Fichier local.settings.json qui définit les variables d’environnement utilisées par votre projet lors de l’exécution locale sur votre ordinateur.

Pour obtenir des exemples complets, consultez l’exemple de projet .NET 8 et l’exemple de projet .NET Framework 4.8.

Références de package

Un projet .NET pour Azure Functions utilisant le modèle Worker isolé utilise un ensemble unique de packages, à la fois pour les principales fonctionnalités et les extensions de liaison.

Packages principaux

Les packages suivants sont requis pour exécuter vos fonctions .NET dans un processus worker isolé :

Version 2.x (préversion)

Les versions 2.x des packages principaux modifient les infrastructures prises en charge et prennent en charge les nouvelles API .NET de ces versions ultérieures. Lorsque vous ciblez .NET 9 (préversion) ou version ultérieure, votre application doit référencer la version 2.0.0-preview1 ou ultérieure des deux packages.

Les versions initiales sont compatibles avec le code écrit sur la version 1.x. Toutefois, pendant la période de préversion, les versions plus récentes peuvent introduire des modifications de comportement susceptibles d’influencer le code que vous écrivez.

Lors de la mise à jour vers les versions 2.x, notez les changements suivants :

  • À compter de la version 2.0.0-preview2, Microsoft.Azure.Functions.Worker.Sdk ajoute des configurations par défaut pour les builds de conteneur SDK.
  • À compter de la version 2.0.0-preview2 de Microsoft.Azure.Functions.Worker :
    • Cette version ajoute la prise en charge de IHostApplicationBuilder. Certains exemples de ce guide incluent des onglets pour afficher des alternatives avec IHostApplicationBuilder. Ces exemples nécessitent les versions 2.x.
    • La validation de l’étendue du fournisseur de services est incluse par défaut si l’exécution a lieu dans un environnement de développement. Ce comportement correspond à celui d’ASP.NET Core.
    • L’option EnableUserCodeException est activée par défaut. La propriété est désormais marquée comme étant obsolète.
    • L’option IncludeEmptyEntriesInMessagePayload est activée par défaut. Lorsque cette option est activée, les charges utiles des déclencheurs qui représentent des collections incluent toujours des entrées vides. Par exemple, si un message est envoyé sans corps, une entrée vide est toujours présente dans string[] pour les données du déclencheur. L’inclusion d’entrées vides facilite le référencement croisé avec les tableaux de métadonnées que la fonction peut également référencer. Vous pouvez désactiver ce comportement en définissant IncludeEmptyEntriesInMessagePayload sur false dans la configuration du service WorkerOptions.
    • La classe ILoggerExtensions est renommée FunctionsLoggerExtensions. Le changement de nom évite une erreur d’appel ambiguë lors de l’utilisation de LogMetric() sur une instance ILogger.

Packages d'extension

Comme les fonctions de processus de travail isolé de .NET utilisent différents types de liaison, elles nécessitent un ensemble unique de paquets d’extension de liaison.

Vous trouverez ces packages d’extension sous Microsoft.Azure.Functions.Worker.Extensions.

Démarrage et configuration

Lorsque vous utilisez le modèle de Worker isolé, vous avez accès au démarrage de votre application de fonction, qui se trouve généralement dans Program.cs. Vous devez créer et démarrer votre propre instance d’hôte. Ainsi, vous disposez également d’un accès direct au pipeline de configuration de votre application. Avec le processus de travail isolé .NET Functions, vous pouvez beaucoup plus facilement ajouter des configurations, injecter des dépendances et exécuter votre propre intergiciel.

Le code suivant présente un exemple de pipeline HostBuilder :

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(s =>
    {
        s.AddApplicationInsightsTelemetryWorkerService();
        s.ConfigureFunctionsApplicationInsights();
        s.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();
        s.Configure<LoggerFilterOptions>(options =>
        {
            // The Application Insights SDK adds a default logging filter that instructs ILogger to capture only Warning and more severe logs. Application Insights requires an explicit override.
            // Log levels can also be configured using appsettings.json. For more information, see https://learn.microsoft.com/en-us/azure/azure-monitor/app/worker-service#ilogger-logs
            LoggerFilterRule? toRemove = options.Rules.FirstOrDefault(rule => rule.ProviderName
                == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");

            if (toRemove is not null)
            {
                options.Rules.Remove(toRemove);
            }
        });
    })
    .Build();

Le code nécessite using Microsoft.Extensions.DependencyInjection;.

Avant d’appeler Build() sur le IHostBuilder, vous devez :

  • Appelez soit ConfigureFunctionsWebApplication() si vous utilisez ASP.NET Core intégration ou ConfigureFunctionsWorkerDefaults() dans le cas contraire. Pour plus d’informations sur ces options, consultez le déclencheur HTTP.
    Si vous écrivez votre application en F#, certaines extensions de déclenchement et de liaison nécessitent une configuration supplémentaire. Consultez la documentation de configuration de l’extension Blobs, de l’extension Tables et de l’extension Cosmos DB lorsque vous envisagez d’utiliser ces extensions dans une application F#.
  • Configurez les services ou la configuration de l'application dont votre projet a besoin. Pour plus d’informations, consultez Configuration.
    Si vous envisagez d’utiliser Application Insights, vous devez appeler AddApplicationInsightsTelemetryWorkerService() et ConfigureFunctionsApplicationInsights() dans le délégué ConfigureServices(). Consultez Limites d’Application Insights pour plus d’informations.

Si votre projet cible .NET Framework 4.8, vous devez également ajouter FunctionsDebugger.Enable(); avant de créer une ressource HostBuilder. Il doit s’agir de la première ligne de votre méthode Main(). Pour plus d’informations, consultez Débogage lors du ciblage du .NET Framework.

Le HostBuilder est utilisé pour générer et renvoyer une instance IHost entièrement initialisée que vous exécutez de façon asynchrone pour démarrer votre application de fonction.

await host.RunAsync();

Configuration

Le type de générateur que vous utilisez détermine la façon dont vous pouvez configurer l’application.

La méthode ConfigureFunctionsWorkerDefaults permet d’ajouter les paramètres nécessaires à l’exécution de l’application de fonction. La méthode inclut les fonctionnalités suivantes :

  • Ensemble de convertisseurs par défaut.
  • Définissez la valeur par défaut de JsonSerializerOptions sur ignorer la casse des noms de propriétés.
  • Intégration à la journalisation Azure Functions.
  • Fonctionnalités et intergiciel de liaison de sortie.
  • Intergiciel d’exécution de fonction.
  • Prise en charge par défaut de gRPC.
.ConfigureFunctionsWorkerDefaults()

L’accès au pipeline du générateur d’hôte vous permet également de définir des configurations spécifiques à l’application lors de l’initialisation. Vous pouvez appeler la méthode ConfigureAppConfiguration sur HostBuilder une ou plusieurs fois pour ajouter les sources de configuration requises par votre code. Pour en savoir plus sur la configuration, consultez Configuration dans ASP.NET Core.

Ces configurations s’appliquent uniquement au code Worker que vous créez et n’influencent pas directement la configuration de l’hôte Functions ou des déclencheurs et des liaisons. Pour apporter des modifications à l’hôte Functions ou à la configuration de déclenchement et de liaison, vous devez toujours utiliser le fichier host.json.

Remarque

Les sources de configuration personnalisées ne peuvent pas être utilisées pour la configuration des déclencheurs et des liaisons. La configuration du déclencheur et de la liaison doit être disponible pour la plateforme Functions, pas seulement votre code d’application. Vous pouvez fournir cette configuration via les fonctionnalités Paramètres d’application, Références Key Vault ou Références App Configuration.

Injection de dépendances

Le modèle Worker isolé utilise des mécanismes .NET standard pour l’injection de services.

Lorsque vous utilisez HostBuilder, appelez ConfigureServices sur le générateur d’hôte et utilisez les méthodes d’extension sur IServiceCollection pour injecter des services spécifiques. L’exemple suivant injecte une dépendance de service singleton :

.ConfigureServices(services =>
{
    services.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();
})

Le code nécessite using Microsoft.Extensions.DependencyInjection;. Pour plus d’informations, consultez Injection de dépendances dans ASP.net Core.

Inscrire des clients Azure

L’injection de dépendances peut être utilisée pour interagir avec d’autres services Azure. Vous pouvez injecter des clients à partir du Kit de développement logiciel (SDK) Azure pour .NET à l’aide du package Microsoft.Extensions.Azure. Après avoir installé le package, inscrivez les clients en appelant AddAzureClients() sur la collection de services dans Program.cs. L’exemple suivant configure un client nommé pour les objets blob Azure :

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Azure;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices((hostContext, services) =>
    {
        services.AddAzureClients(clientBuilder =>
        {
            clientBuilder.AddBlobServiceClient(hostContext.Configuration.GetSection("MyStorageConnection"))
                .WithName("copierOutputBlob");
        });
    })
    .Build();

host.Run();

L’exemple suivant montre comment utiliser cette inscription et les types de Kits de développement logiciel (SDK) pour copier le contenu d’objets blobs en tant que flux d’un conteneur vers un autre à l’aide d’un client injecté :

using Microsoft.Extensions.Azure;
using Microsoft.Extensions.Logging;

namespace MyFunctionApp
{
    public class BlobCopier
    {
        private readonly ILogger<BlobCopier> _logger;
        private readonly BlobContainerClient _copyContainerClient;

        public BlobCopier(ILogger<BlobCopier> logger, IAzureClientFactory<BlobServiceClient> blobClientFactory)
        {
            _logger = logger;
            _copyContainerClient = blobClientFactory.CreateClient("copierOutputBlob").GetBlobContainerClient("samples-workitems-copy");
            _copyContainerClient.CreateIfNotExists();
        }

        [Function("BlobCopier")]
        public async Task Run([BlobTrigger("samples-workitems/{name}", Connection = "MyStorageConnection")] Stream myBlob, string name)
        {
            await _copyContainerClient.UploadBlobAsync(name, myBlob);
            _logger.LogInformation($"Blob {name} copied!");
        }

    }
}

Le ILogger<T> dans cet exemple a également été obtenu par injection de dépendances. Il est donc enregistré automatiquement. Pour en savoir plus sur les options de configuration de la journalisation, consultez Journalisation.

Conseil

L’exemple utilisait une chaîne littérale pour le nom du client dans Program.cs et dans la fonction. Envisagez plutôt d’utiliser une chaîne constante partagée définie sur la classe de fonction. Par exemple, vous pouvez ajouter public const string CopyStorageClientName = nameof(_copyContainerClient);, puis référencer BlobCopier.CopyStorageClientName dans les deux emplacements. Vous pouvez également définir le nom de la section de configuration avec la fonction plutôt que dans Program.cs.

Middleware

Le modèle de Worker isolé prend également en charge l’inscription d’intergiciel, à nouveau à l’aide d’un modèle similaire à ce qui existe dans ASP.NET. Ce modèle vous donne la possibilité d’injecter une logique dans le pipeline d’appel, et avant et après l’exécution des fonctions.

La méthode d’extension ConfigureFunctionsWorkerDefaults a une surcharge qui vous permet d’inscrire votre propre intergiciel, comme vous pouvez le voir dans l’exemple suivant.

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(workerApplication =>
    {
        // Register our custom middlewares with the worker

        workerApplication.UseMiddleware<ExceptionHandlingMiddleware>();

        workerApplication.UseMiddleware<MyCustomMiddleware>();

        workerApplication.UseWhen<StampHttpHeaderMiddleware>((context) =>
        {
            // We want to use this middleware only for http trigger invocations.
            return context.FunctionDefinition.InputBindings.Values
                          .First(a => a.Type.EndsWith("Trigger")).Type == "httpTrigger";
        });
    })
    .Build();

La méthode d’extension UseWhen peut être utilisée pour inscrire un intergiciel qui est exécuté de manière conditionnelle. Vous devez passer à cette méthode un prédicat qui retourne une valeur booléenne, et le middleware participe au pipeline de traitement d’appel lorsque la valeur de retour du prédicat est true.

Les méthodes d’extension suivantes sur FunctionContext facilitent l’utilisation des intergiciels dans le modèle isolé.

Méthode Description
GetHttpRequestDataAsync Obtient l’instance HttpRequestData lorsqu’elle est appelée par un déclencheur HTTP. Cette méthode retourne une instance de ValueTask<HttpRequestData?>, ce qui est utile lorsque vous souhaitez lire les données de message, telles que les en-têtes de requête et les cookies.
GetHttpResponseData Obtient l’instance HttpResponseData lorsqu’elle est appelée par un déclencheur HTTP.
GetInvocationResult Obtient une instance de InvocationResult, qui représente le résultat de l’exécution de la fonction actuelle. Utilisez la propriété Value pour obtenir ou définir la valeur en fonction des besoins.
GetOutputBindings Obtient les entrées de liaison de sortie pour l’exécution de la fonction actuelle. Chaque entrée dans les résultats de cette méthode est de type OutputBindingData. Vous pouvez utiliser la propriété Value pour obtenir ou définir la valeur en fonction des besoins.
BindInputAsync Lie un élément de liaison d’entrée pour l’instance demandée BindingMetadata. Par exemple, vous pouvez utiliser cette méthode lorsque vous avez une fonction avec une liaison d’entrée BlobInput qui doit être utilisée par votre intergiciel.

Voici un exemple d’implémentation d’intergiciel qui lit l’instance HttpRequestData et met à jour l’instance HttpResponseData pendant l’exécution de la fonction :

internal sealed class StampHttpHeaderMiddleware : IFunctionsWorkerMiddleware
{
    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
        var requestData = await context.GetHttpRequestDataAsync();

        string correlationId;
        if (requestData!.Headers.TryGetValues("x-correlationId", out var values))
        {
            correlationId = values.First();
        }
        else
        {
            correlationId = Guid.NewGuid().ToString();
        }

        await next(context);

        context.GetHttpResponseData()?.Headers.Add("x-correlationId", correlationId);
    }
}

Cet intergiciel recherche la présence d’un en-tête de requête spécifique (x-correlationId) et, lorsque celui est présent, l’intergiciel utilise la valeur d’en-tête pour mettre un tampon sur un en-tête de réponse. Dans le cas contraire, il génère une nouvelle valeur GUID et l’utilise pour l’horodatage de l’en-tête de réponse. Pour obtenir un exemple plus complet de l’utilisation d’un intergiciel personnalisé dans votre application de fonction, consultez l'exemple de référence d’intergiciel personnalisé.

Personnalisation de la sérialisation JSON

Par défaut, le modèle de worker isolé utilise System.Text.Json. Vous pouvez personnaliser le comportement du sérialiseur en configurant les services dans le cadre de votre fichier Program.cs. Cette section traite de la sérialisation à usage général et n’influence pas la sérialisation JSON du déclencheur HTTP avec intégration ASP.NET Core, qui doit être configurée séparément.

L’exemple suivant montre cette utilisation de ConfigureFunctionsWebApplication, mais elle fonctionnera également pour ConfigureFunctionsWorkerDefaults :

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication((IFunctionsWorkerApplicationBuilder builder) =>
    {
        builder.Services.Configure<JsonSerializerOptions>(jsonSerializerOptions =>
        {
            jsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
            jsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
            jsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;

            // override the default value
            jsonSerializerOptions.PropertyNameCaseInsensitive = false;
        });
    })
    .Build();

host.Run();

Vous souhaiterez peut-être utiliser JSON.NET (Newtonsoft.Json) à la place pour la sérialisation. Pour ce faire, vous devez installer le package Microsoft.Azure.Core.NewtonsoftJson. Ensuite, dans votre inscription de service, vous réaffectez la propriété Serializer sur la configuration WorkerOptions. L’exemple suivant montre cette utilisation de ConfigureFunctionsWebApplication, mais elle fonctionnera également pour ConfigureFunctionsWorkerDefaults :

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication((IFunctionsWorkerApplicationBuilder builder) =>
    {
        builder.Services.Configure<WorkerOptions>(workerOptions =>
        {
            var settings = NewtonsoftJsonObjectSerializer.CreateJsonSerializerSettings();
            settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
            settings.NullValueHandling = NullValueHandling.Ignore;

            workerOptions.Serializer = new NewtonsoftJsonObjectSerializer(settings);
        });
    })
    .Build();

host.Run();

Méthodes reconnues en tant que fonctions

Une méthode de fonction est une méthode publique d’une classe publique avec un attribut Function appliqué à la méthode et un attribut déclencheur appliqué à un paramètre d’entrée, comme illustré dans l’exemple suivant :

[Function(nameof(QueueFunction))]
[QueueOutput("output-queue")]
public string[] Run([QueueTrigger("input-queue")] Album myQueueItem, FunctionContext context)

L’attribut de déclencheur spécifie le type de déclencheur et lie les données d’entrée à un paramètre de méthode. L’exemple de fonction précédent est déclenché par un message de file d’attente, qui est lui-même transmis à la méthode dans le paramètre myQueueItem.

L’attribut Function marque une méthode comme point d’entrée de la fonction. Le nom doit être unique au sein d’un projet, commencer par une lettre et ne contenir que des lettres, des chiffres, _ et -, jusqu’à 127 caractères. Les modèles de projets créent souvent une méthode nommée Run, mais le nom de la méthode peut être n’importe quel nom de méthode C# valide. La méthode doit être un membre public d’une classe publique. Il doit généralement s’agir d’une méthode d’instance afin que les services puissent être transmis via l’injection de dépendances.

Paramètres de fonction

Voici quelques-uns des paramètres que vous pouvez inclure dans le cadre d’une signature de méthode de fonction :

  • Des liaisons, qui sont marquées comme telles en décorant les paramètres en tant qu’attributs. La fonction doit contenir exactement un paramètre de déclencheur.
  • Un objet de contexte d’exécution, qui fournit des informations sur l’appel actuel.
  • Un jeton d’annulation, utilisé pour l’arrêt approprié.

Contexte d’exécution

Le processus isolé .NET transmet un objet FunctionContext à vos méthodes de fonction. Cet objet vous permet d’obtenir une instance ILogger pour écrire dans les journaux en appelant la méthode GetLogger et en fournissant une chaîne categoryName. Vous pouvez utiliser ce contexte pour obtenir un ILogger sans avoir à utiliser l’injection de dépendances. Pour en savoir plus, consultez Journalisation.

Jetons d’annulation

Une fonction peut accepter un paramètre CancellationToken qui permet au système d’exploitation de notifier votre code quand la fonction est sur le point de se terminer. Vous pouvez utiliser cette notification pour vous assurer que la fonction ne s’arrête pas de manière inattendue et laisse les données dans un état incohérent.

Les jetons d’annulation sont pris en charge dans les fonctions .NET lors de l’exécution dans un processus worker isolé. L’exemple suivant lève une exception lorsqu’une requête d’annulation est reçue :

[Function(nameof(ThrowOnCancellation))]
public async Task ThrowOnCancellation(
    [EventHubTrigger("sample-workitem-1", Connection = "EventHubConnection")] string[] messages,
    FunctionContext context,
    CancellationToken cancellationToken)
{
    _logger.LogInformation("C# EventHub {functionName} trigger function processing a request.", nameof(ThrowOnCancellation));

    foreach (var message in messages)
    {
        cancellationToken.ThrowIfCancellationRequested();
        await Task.Delay(6000); // task delay to simulate message processing
        _logger.LogInformation("Message '{msg}' was processed.", message);
    }
}

L’exemple suivant effectue des actions de nettoyage lorsqu’une requête d’annulation est reçue :

[Function(nameof(HandleCancellationCleanup))]
public async Task HandleCancellationCleanup(
    [EventHubTrigger("sample-workitem-2", Connection = "EventHubConnection")] string[] messages,
    FunctionContext context,
    CancellationToken cancellationToken)
{
    _logger.LogInformation("C# EventHub {functionName} trigger function processing a request.", nameof(HandleCancellationCleanup));

    foreach (var message in messages)
    {
        if (cancellationToken.IsCancellationRequested)
        {
            _logger.LogInformation("A cancellation token was received, taking precautionary actions.");
            // Take precautions like noting how far along you are with processing the batch
            _logger.LogInformation("Precautionary activities complete.");
            break;
        }

        await Task.Delay(6000); // task delay to simulate message processing
        _logger.LogInformation("Message '{msg}' was processed.", message);
    }
}

Liaisons

Les liaisons sont définies à l’aide d’attributs sur les méthodes, paramètres et types de retour. Les liaisons peuvent fournir des données sous forme de chaînes, de tableaux et de types sérialisables, telles que des objets de classe anciens simples (POCO). Pour certaines extensions de liaison, vous pouvez également lier à des types propres au service définis dans des kits SDK de service.

Pour les déclencheurs HTTP, consultez la section Déclencheur HTTP.

Pour obtenir un ensemble complet d’exemples de référence utilisant des déclencheurs et des liaisons avec des fonctions de processus Worker isolé, consultez l’exemple de référence des extensions de liaison.

Liaisons d’entrée

Une fonction peut avoir zéro ou plusieurs liaisons d’entrée susceptibles de transmettre des données à une fonction. Comme les déclencheurs, les liaisons d’entrée sont définies en appliquant un attribut de liaison à un paramètre d’entrée. Lorsque la fonction s’exécute, le runtime tente d’obtenir les données spécifiées dans la liaison. Les données demandées dépendent souvent des informations fournies par le déclencheur à l’aide de paramètres de liaison.

Liaisons de sortie

Pour écrire dans une liaison de sortie, vous devez appliquer un attribut de liaison de sortie à la méthode de fonction qui définit la manière d’écrire dans le service lié. La valeur renvoyée par la méthode est écrite dans la liaison de sortie. Par exemple, l’exemple suivant écrit une valeur de chaîne dans une file d’attente de messages nommée output-queue à l’aide d’une liaison de sortie :

[Function(nameof(QueueFunction))]
[QueueOutput("output-queue")]
public string[] Run([QueueTrigger("input-queue")] Album myQueueItem, FunctionContext context)
{
    // Use a string array to return more than one message.
    string[] messages = {
        $"Album name = {myQueueItem.Name}",
        $"Album songs = {myQueueItem.Songs}"};

    _logger.LogInformation("{msg1},{msg2}", messages[0], messages[1]);

    // Queue Output messages
    return messages;
}

Liaisons de sortie multiples

Les données écrites dans une liaison de sortie correspondent toujours à la valeur renvoyée de la fonction. S’il vous faut écrire dans plusieurs liaisons de sortie, vous devez créer un type de retour personnalisé. Ce type de retour doit présenter l’attribut de liaison de sortie appliqué à une ou plusieurs propriétés de la classe. L’exemple suivant est une fonction déclenchée par HTTP à l’aide de l’intégration ASP.NET Core qui écrit à la fois dans la réponse HTTP et dans une liaison de sortie de file d’attente :

public class MultipleOutputBindings
{
    private readonly ILogger<MultipleOutputBindings> _logger;

    public MultipleOutputBindings(ILogger<MultipleOutputBindings> logger)
    {
        _logger = logger;
    }

    [Function("MultipleOutputBindings")]
    public MyOutputType Run([HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req)
    {
        _logger.LogInformation("C# HTTP trigger function processed a request.");
        var myObject = new MyOutputType
        {
            Result = new OkObjectResult("C# HTTP trigger function processed a request."),
            MessageText = "some output"
        };
        return myObject;
    }

    public class MyOutputType
    {
        [HttpResult]
        public IActionResult Result { get; set; }

        [QueueOutput("myQueue")]
        public string MessageText { get; set; }
    }
}

Lorsque vous utilisez des types de retour personnalisés pour plusieurs liaisons de sortie avec l’intégration ASP.NET Core, vous devez ajouter l’attribut [HttpResult] à la propriété qui fournit le résultat. L’attribut HttpResult est disponible lorsque vous utilisez SDK 1.17.3-preview2 ou version ultérieure , ainsi que version 3.2.0 ou ultérieure de l’extension HTTP et version 1.3.0 ou ultérieure de l’extension ASP.NET Core.

Types de kit de développement logiciel (SDK)

Pour certains types de liaison spécifiques au service, les données de liaison peuvent être fournies à l’aide de types provenant de kits de développement logiciel (SDK) de service et d’infrastructures. Ceux-ci offrent des fonctionnalités supplémentaires au-delà de ce qu’une chaîne sérialisée ou un objet CLR traditionnel (POCO, Plain-Old CLR Object) peut offrir. Pour utiliser les types plus récents, votre projet doit être mis à jour pour utiliser des versions plus récentes des dépendances principales.

Dépendance Version requise
Microsoft.Azure.Functions.Worker 1.18.0 ou version ultérieure
Microsoft.Azure.Functions.Worker.Sdk 1.13.0 ou version ultérieure

Lorsque vous testez des types de SDK localement sur votre ordinateur, vous devez également utiliser Azure Functions Core Tools version 4.0.5000 ou ultérieure. Vous pouvez vérifier votre version actuelle à l’aide de la commande func version.

Chaque extension de déclencheur et de liaison requiert également sa propre version minimale, qui est décrite dans les articles de référence sur les extensions. Les liaisons propres au service suivantes fournissent des types de SDK :

Service Déclencheur Liaison d’entrée Liaison de sortie
Objets blob Azure En disponibilité générale En disponibilité générale Types de SDK non recommandés.1
Files d’attente Azure En disponibilité générale La liaison d’entrée n’existe pas Types de SDK non recommandés.1
Azure Service Bus En disponibilité générale La liaison d’entrée n’existe pas Types de SDK non recommandés.1
Azure Event Hubs En disponibilité générale La liaison d’entrée n’existe pas Types de SDK non recommandés.1
Azure Cosmos DB Types de SDK non utilisés2 En disponibilité générale Types de SDK non recommandés.1
Tables Azure Le déclencheur n’existe pas En disponibilité générale Types de SDK non recommandés.1
Azure Event Grid En disponibilité générale La liaison d’entrée n’existe pas Types de SDK non recommandés.1

1 Pour les scénarios de sortie dans lesquels vous utiliseriez un type de SDK, vous devriez créer et utiliser directement des clients SDK plutôt que d’utiliser une liaison de sortie. Pour obtenir un exemple d’injection de dépendances, consultez Inscrire des clients Azure.

2 Le déclencheur Cosmos DB utilise le flux de modification Azure Cosmos DB et expose les éléments dudit flux en tant que types de JSON sérialisables. L’absence de types de Kit de développement logiciel (SDK) est par conception pour ce scénario.

Remarque

Lors de l’utilisation d’expressions de liaison qui s’appuient sur des données de déclencheur, les types de SDK pour le déclencheur même ne sont pas pris en charge.

Déclencheur HTTP

Le déclencheur HTTP permettent d’invoquer une fonction par une requête HTTP. Deux approches différentes peuvent être utilisées :

  • Un modèle d’intégration ASP.NET Core qui utilise des concepts familiers aux développeurs ASP.NET Core
  • Un modèle intégré qui ne nécessite pas de dépendances supplémentaires et utilise des types personnalisés pour les requêtes et les réponses HTTP Cette approche est conservée à des fins de compatibilité descendante avec les applications Worker isolé .NET antérieures.

Intégration ASP.NET Core

Cette section montre comment utiliser les objets de requête et de réponse HTTP sous-jacents à l’aide de types provenant de ASP.NET Core notamment HttpRequest, HttpResponse et IActionResult. Ce modèle n’est pas disponible pour les applications ciblant le .NET Framework, qui doivent plutôt utiliser le modèle intégré.

Remarque

Toutes les fonctionnalités de ASP.NET Core ne sont pas exposées par ce modèle. Plus précisément, le pipeline ASP.NET Core intergiciel et les fonctionnalités de routage ne sont pas disponibles. L’intégration ASP.NET Core vous oblige à utiliser des packages mis à jour.

Pour activer l’intégration ASP.NET Core pour HTTP :

  1. Ajoutez une référence dans votre projet au package Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore, version 1.0.0 ou ultérieure.

  2. Mettez à jour votre projet de façon à utiliser ces versions de package spécifiques :

  3. Dans votre fichier Program.cs, mettez à jour la configuration du générateur d’hôte pour appeler ConfigureFunctionsWebApplication(). Ceci remplace ConfigureFunctionsWorkerDefaults() qui est normalement utilisé dans cette méthode. L’exemple suivant montre une configuration minimale sans autres personnalisations :

    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.Hosting;
    
    var host = new HostBuilder()
        .ConfigureFunctionsWebApplication()
        .Build();
    
    host.Run();
    
  4. Mettez à jour les fonctions déclenchées par HTTP existantes de façon à utiliser les types ASP.NET Core. Cet exemple montre le HttpRequest standard et un IActionResult utilisé pour une fonction « hello, world » simple :

    [Function("HttpFunction")]
    public IActionResult Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req)
    {
        return new OkObjectResult($"Welcome to Azure Functions, {req.Query["name"]}!");
    }
    

Sérialisation JSON avec intégration ASP.NET Core

ASP.NET Core a sa propre couche de sérialisation, et n’est pas affecté par la personnalisation de la configuration de sérialisation générale. Pour personnaliser le comportement de sérialisation utilisé pour vos déclencheurs HTTP, vous devez inclure un appel .AddMvc() dans le cadre de l’inscription de service. Le IMvcBuilder retourné peut être utilisé pour modifier les paramètres de sérialisation JSON d’ASP.NET Core. L’exemple suivant montre comment configurer JSON.NET (Newtonsoft.Json) pour la sérialisation à l’aide de cette approche :

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services =>
    {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
        services.AddMvc().AddNewtonsoftJson();
    })
    .Build();
host.Run();

Modèle HTTP intégré

Dans le modèle intégré, le système traduit le message de requête HTTP entrant en objet HttpRequestData qui est transmis à la fonction. Cet objet fournit les données de la requête, notamment Headers, Cookies, Identities, URL, et éventuellement un message Body. Cet objet est une représentation de la requête HTTP, mais il n’est pas directement connecté à l’écouteur HTTP sous-jacent ou au message reçu.

De même, la fonction retourne un objet HttpResponseData, qui fournit les données utilisées pour créer la réponse HTTP, notamment le message StatusCode, Headers et éventuellement un message Body.

L’exemple suivant montre l’utilisation de HttpRequestData et HttpResponseData :

[Function(nameof(HttpFunction))]
public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequestData req,
    FunctionContext executionContext)
{
    var logger = executionContext.GetLogger(nameof(HttpFunction));
    logger.LogInformation("message logged");

    var response = req.CreateResponse(HttpStatusCode.OK);
    response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
    response.WriteString("Welcome to .NET isolated worker !!");

    return response;
}

Logging

Vous pouvez écrire dans les journaux en utilisant une instance ILogger<T> ou ILogger. L’enregistreur d’événements peut être obtenu par injection de dépendances d’un ILogger<T> ou d’un ILoggerFactory :

public class MyFunction {
    
    private readonly ILogger<MyFunction> _logger;
    
    public MyFunction(ILogger<MyFunction> logger) {
        _logger = logger;
    }
    
    [Function(nameof(MyFunction))]
    public void Run([BlobTrigger("samples-workitems/{name}", Connection = "")] string myBlob, string name)
    {
        _logger.LogInformation($"C# Blob trigger function Processed blob\n Name: {name} \n Data: {myBlob}");
    }

}

L’enregistreur d’événements peut également être obtenu à partir d’un objet FunctionContext passé à votre fonction. Appelez la méthode GetLogger<T> ou GetLogger, en transmettant une valeur de chaîne correspondant au nom de la catégorie dans laquelle les journaux sont écrits. La catégorie correspond généralement au nom de la fonction spécifique à partir de laquelle les journaux sont écrits. Pour en savoir plus sur les catégories, consultez l’article relative à la surveillance.

Utilisez les méthodes de ILogger<T> et ILogger pour écrire différents niveaux de journalisation, comme LogWarning ou LogError. Pour en savoir plus sur les niveaux de journalisation, consultez l’article relatif à la surveillance. Vous pouvez personnaliser les niveaux de journal pour les composants ajoutés à votre code en inscrivant des filtres :

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services =>
    {
        // Registers IHttpClientFactory.
        // By default this sends a lot of Information-level logs.
        services.AddHttpClient();
    })
    .ConfigureLogging(logging =>
    {
        // Disable IHttpClientFactory Informational logs.
        // Note -- you can also remove the handler that does the logging: https://github.com/aspnet/HttpClientFactory/issues/196#issuecomment-432755765 
        logging.AddFilter("System.Net.Http.HttpClient", LogLevel.Warning);
    })
    .Build();

Dans le cadre de la configuration de votre application dans Program.cs, vous pouvez également définir le comportement de la façon dont les erreurs sont exposées à vos journaux. Le comportement par défaut dépend du type de générateur que vous utilisez.

Lorsque vous utilisez HostBuilder, par défaut, les exceptions levées par votre code peuvent être encapsulées dans RpcException. Pour supprimer cette couche supplémentaire, définissez la propriété EnableUserCodeException sur « true » dans le cadre de la configuration du générateur :

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.Hosting;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(builder => {}, options =>
    {
        options.EnableUserCodeException = true;
    })
    .Build();

host.Run();

Application Insights

Vous pouvez configurer votre application de processus isolée pour qu’elle émette des journaux directement vers Application Insights. Ce comportement remplace le comportement par défaut qui consiste à relayer les journaux via l’hôte. À moins que vous n’utilisiez .NET Aspire, la configuration de l’intégration directe d’Application Insights est recommandée, car elle vous permet de contrôler la façon dont ces journaux sont émis.

L’intégration d’Application Insights n’est pas activée par défaut dans toutes les expériences de configuration. Certains modèles créent des projets Functions avec les packages nécessaires et le code de démarrage mis en commentaire. Si vous souhaitez utiliser l’intégration Application Insights, vous pouvez supprimer les marques de commentaire de ces lignes dans Program.cs et dans le fichier .csproj du projet. Les instructions contenues dans le reste de cette section décrivent également comment activer l’intégration.

Si votre projet fait partie d’une orchestration .NET Aspire, il utilise OpenTelemetry pour la surveillance à la place. Vous ne devez pas activer l’intégration directe d’Application Insights dans les projets .NET Aspire. Au lieu de cela, configurez l’exportateur Azure Monitor OpenTelemetry dans le cadre du projet de service par défaut. Si votre projet Functions utilise l’intégration Application Insights dans un contexte .NET Aspire, l’application échoue au démarrage.

Installer des packages

Pour écrire des journaux directement dans Application Insights à partir de votre code, ajoutez des références à ces packages dans votre projet :

Vous pouvez exécuter les commandes suivantes pour ajouter ces références à votre projet :

dotnet add package Microsoft.ApplicationInsights.WorkerService
dotnet add package Microsoft.Azure.Functions.Worker.ApplicationInsights

Configurer le démarrage

Une fois les packages installés, vous devez appeler AddApplicationInsightsTelemetryWorkerService() et ConfigureFunctionsApplicationInsights() pendant la configuration du service dans votre fichier Program.cs, comme dans cet exemple :

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
    
var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services => {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
    })
    .Build();

host.Run();

L’appel à ConfigureFunctionsApplicationInsights() ajoute un ITelemetryModule, qui écoute un ActivitySource défini par Functions. Cela crée la télémétrie de dépendance requises pour prendre en charge le suivi distribué. Pour en savoir plus sur AddApplicationInsightsTelemetryWorkerService() et sur l’utilisation et la façon de l’utiliser, consultez Application Insights pour les applications de service Worker.

Gestion des niveaux de journal

Important

L’hôte Functions et le worker de processus isolé ont une configuration distincte pour les niveaux de journalisation, etc. Toute configuration Application Insights dans host.json n’affecte pas la journalisation à partir du worker. De même, la configuration effectuée dans votre code worker n’aura pas d’impact sur la journalisation à partir de l’hôte. Vous devez appliquer des modifications aux deux emplacements si votre scénario nécessite une personnalisation dans les deux couches.

Le reste de votre application continue de fonctionner avec ILogger et ILogger<T>. Toutefois, par défaut, le kit de développement logiciel (SDK) Application Insights ajoute un filtre de journalisation qui indique à l’enregistreur d’événements de capturer uniquement les avertissements et les journaux plus graves. Si vous souhaitez désactiver ce comportement, supprimez la règle de filtre dans le cadre de la configuration du service :

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services => {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
    })
    .ConfigureLogging(logging =>
    {
        logging.Services.Configure<LoggerFilterOptions>(options =>
        {
            LoggerFilterRule defaultRule = options.Rules.FirstOrDefault(rule => rule.ProviderName
                == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");
            if (defaultRule is not null)
            {
                options.Rules.Remove(defaultRule);
            }
        });
    })
    .Build();

host.Run();

Optimisation des performances

Cette section décrit les options que vous pouvez activer pour améliorer les performances autour du démarrage à froid.

En général, votre application doit utiliser les dernières versions de ses dépendances principales. Au minimum, vous devez mettre à jour votre projet comme suit :

  1. Mettez à niveau Microsoft.Azure.Functions.Worker vers la version 1.19.0 ou ultérieure.
  2. Mettez à niveau Microsoft.Azure.Functions.Worker.Sdk vers la version 1.16.4 ou une version ultérieure.
  3. Ajoutez une référence de framework à Microsoft.AspNetCore.App, sauf si votre application cible .NET Framework.

L’extrait suivant montre cette configuration dans le contexte d’un fichier projet :

  <ItemGroup>
    <FrameworkReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.21.0" />
    <PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.16.4" />
  </ItemGroup>

Espaces réservés

Les espaces réservés sont une fonctionnalité de plateforme qui améliore le démarrage à froid pour les applications ciblant .NET 6 ou une version ultérieure. Pour utiliser cette optimisation, vous devez activer explicitement les espaces réservés en effectuant ces étapes :

  1. Mettez à jour la configuration de votre projet de façon à utiliser les dernières versions de dépendances, comme indiqué dans la section précédente.

  2. Affectez la valeur WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED au paramètre d’application 1, ce que vous pouvez faire à l’aide de cette commande az functionapp config appsettings set :

    az functionapp config appsettings set -g <groupName> -n <appName> --settings 'WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED=1'
    

    Dans cet exemple, remplacez <groupName> par le nom de votre groupe de ressources, et <appName> par le nom de votre application de fonction.

  3. Vérifiez que la propriété netFrameworkVersion de l’application de fonction correspond à l’infrastructure cible de votre projet, qui doit être .NET 6 ou version ultérieure. Pour ce faire, utilisez cette commande az functionapp config set :

    az functionapp config set -g <groupName> -n <appName> --net-framework-version <framework>
    

    Dans cet exemple, remplacez également <framework> par la chaîne de version appropriée, telle que v8.0, en fonction de votre version cible de .NET.

  4. Vérifiez que votre application de fonction est configurée de façon à utiliser un processus 64 bits, ce que vous pouvez faire à l’aide de cette commande az functionapp config set :

    az functionapp config set -g <groupName> -n <appName> --use-32bit-worker-process false
    

Important

En cas d’affectation de la valeur 1 à WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED, toutes les autres configurations d’application de fonction doivent être définies correctement. Autrement, votre application de fonction risque de ne pas démarrer.

Exécuteur optimisé

L’exécuteur de fonction est un composant de la plateforme qui provoque l’exécution d’appels. Une version optimisée de ce composant est activée par défaut à partir de la version 1.16.2 du Kit de développement logiciel (SDK). Aucune configuration supplémentaire n’est nécessaire.

ReadyToRun

Vous pouvez compiler votre application de fonction en tant que binaires ReadyToRun. ReadyToRun est une forme de compilation à l’avance qui peut améliorer les performances de démarrage pour réduire l’effet des démarrages à froid lors de l’exécution dans un Plan de consommation. ReadyToRun est disponible dans .NET 6 et versions ultérieures et requiert laversion 4.0 ou ultérieure d’Azure Functions Runtime.

ReadyToRun vous oblige à générer le projet sur l’architecture de runtime de l’application d’hébergement. Si elles ne sont pas alignées, votre application rencontrera une erreur au démarrage. Sélectionnez votre identificateur de runtime dans ce tableau :

Système d'exploitation L’application est une application 32 bits1 Identificateur de runtime
Windows True win-x86
Windows False win-x64
Linux True N/A (non pris en charge)
Linux False linux-x64

1 Seules les applications 64 bits sont éligibles à d’autres optimisations des performances.

Pour vérifier si votre application Windows est 32 bits ou 64 bits, vous pouvez exécuter la commande CLI suivante, en remplaçant <group_name> par le nom de votre groupe de ressources et <app_name> par le nom de votre application. Une sortie « true » indique que l’application est 32 bits et « false » que l’application est 64 bits.

 az functionapp config show -g <group_name> -n <app_name> --query "use32BitWorkerProcess"

Vous pouvez changer votre application en application 64 bits avec la commande suivante, en utilisant les mêmes substitutions :

az functionapp config set -g <group_name> -n <app_name> --use-32bit-worker-process false`

Pour compiler votre projet en tant que ReadyToRun, mettez à jour votre fichier projet en ajoutant les éléments <PublishReadyToRun> et <RuntimeIdentifier>. Les exemples suivants montrent une configuration de publication sur une application de fonction Windows 64 bits.

<PropertyGroup>
  <TargetFramework>net8.0</TargetFramework>
  <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  <RuntimeIdentifier>win-x64</RuntimeIdentifier>
  <PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>

Si vous ne souhaitez pas définir le <RuntimeIdentifier> dans le cadre du fichier projet, vous pouvez également le configurer dans le cadre du mouvement de publication lui-même. Par exemple, avec une application de fonction Windows 64 bits, la commande CLI .NET serait :

dotnet publish --runtime win-x64

Dans Visual Studio, l’option Runtime cible dans le profil de publication doit être définie sur l’identificateur de runtime correct. Lorsqu’il est défini sur la valeur par défaut Portable, ReadyToRun n’est pas utilisé.

Déployer sur Azure Functions

Lorsque vous déployez votre projet de code de fonction sur Azure, il doit s’exécuter dans une application de fonction ou dans un conteneur Linux. L’application de fonction et les autres ressources Azure requises doivent exister avant que vous déployiez votre code.

Vous pouvez également déployer votre application de fonction dans un conteneur Linux. Pour plus d’informations, consultez Utilisation des conteneurs et d’Azure Functions.

Créer des ressources Azure

Vous pouvez créer votre application de fonction et les autres ressources requises dans Azure en appliquant l’une des méthodes suivantes :

  • Visual Studio : Visual Studio peut créer des ressources pour vous pendant le processus de publication de code.
  • Visual Studio Code : Visual Studio Code peut se connecter à votre abonnement, créer les ressources nécessaires à votre application, puis publier votre code.
  • Azure CLI : vous pouvez utiliser Azure CLI pour créer les ressources requises dans Azure.
  • Azure PowerShell : vous pouvez utiliser Azure PowerShell pour créer les ressources requises dans Azure.
  • Modèles de déploiement : vous pouvez utiliser des modèles ARM et des fichiers Bicep pour automatiser le déploiement des ressources requises sur Azure. Vérifiez que votre modèle inclut tous les paramètres requis.
  • Portail Azure : vous pouvez créer les ressources requises dans le portail Azure.

Publication de votre application

Après avoir créé votre application de fonction et autres ressources requises dans Azure, vous pouvez déployer le projet de code sur Azure en appliquant l’une des méthodes suivantes :

Pour plus d’informations, consultez Technologies de déploiement dans Azure Functions.

Charge utile de déploiement

De nombreuses méthodes de déploiement utilisent une archive zip. Si vous créez vous-même l’archive zip, elle doit suivre la structure décrite dans cette section. Si ce n’est pas le cas, votre application peut rencontrer des erreurs au démarrage.

La charge utile de déploiement doit correspondre à la sortie d’une commande dotnet publish, mais sans le dossier parent englobant. L’archive zip doit être effectuée à partir des fichiers suivants :

  • .azurefunctions/
  • extensions.json
  • functions.metadata
  • host.json
  • worker.config.json
  • Exécutable de votre projet (application console)
  • Autres fichiers et répertoires de prise en charge homologues à cet exécutable

Ces fichiers sont générés par le processus de génération et ne sont pas destinés à être modifiés directement.

Lors de la préparation d’une archive zip pour le déploiement, vous devez uniquement compresser le contenu du répertoire de sortie, et non pas le répertoire englobant lui-même. Lorsque l’archive est extraite dans le répertoire de travail actuel, les fichiers répertoriés ci-dessus doivent être immédiatement visibles.

Conditions requises pour le déploiement

Il existe quelques conditions requises pour exécuter des fonctions .NET dans le modèle Worker isolé dans Azure, en fonction du système d’exploitation :

Lorsque vous créez votre application de fonction dans Azure à l’aide des méthodes de la section précédente, ces paramètres requis sont ajoutés pour vous. Lorsque vous créez ces ressources à l’aide de modèles ARM ou de fichiers Bicep pour l’automatisation, vous devez veiller à les définir dans le modèle.

Aspire .NET (préversion)

.NET Aspire est une pile d’opinion qui simplifie le développement d’applications distribuées dans le cloud. Vous pouvez inscrire des projets de modèle de worker isolé .NET 8 et .NET 9 dans les orchestrations Aspire 9.0 à l’aide de la prise en charge de la préversion. La section décrit les exigences principales pour l’inscription.

Cette intégration nécessite une configuration spécifique :

  • Utilisez Aspire 9.0 ou version ultérieure et le SDK .NET 9. Aspire 9.0 prend en charge les frameworks .NET 8 et .NET 9.
  • Si vous utilisez Visual Studio, mettez à jour vers la version 17.12 ou ultérieure. Vous devez également disposer de la dernière version des outils Functions pour Visual Studio. Pour rechercher des mises à jour, accédez à Outils>Options, choisissez Azure Functions sous Projets et solutions. Sélectionnez Rechercher les mises à jour et installez les mises à jour comme indiqué.
  • Dans le projet d’hôte d’application Aspire :
    • Vous devez référencer Aspire.Hosting.Azure.Functions.
    • Vous devez disposer d’une référence de projet à votre projet Functions.
    • Dans le Program.cs de l’hôte d’application, vous devez également inclure le projet en appelant AddAzureFunctionsProject<TProject>() sur votre IDistributedApplicationBuilder. Cette méthode est utilisée au lieu de AddProject<TProject>() que vous utilisez pour d’autres types de projet. Si vous utilisez uniquement AddProject<TProject>(), le projet Functions ne démarre pas correctement.
  • Dans le projet Functions :
    • Vous devez référencer les versions 2.x de Microsoft.Azure.Functions.Worker et Microsoft.Azure.Functions.Worker.Sdk. Vous devez également mettre à jour toutes les références à Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore que vous avez vers la version 2.x.
    • Votre Program.cs doit utiliser la version IHostApplicationBuilder du démarrage de l’instance hôte.
    • Si vous souhaitez utiliser votre service par défaut Aspire, vous devez inclure une référence de projet au projet de service par défaut. Avant de créer votre IHostApplicationBuilder dans Program.cs, vous devez également inclure un appel à builder.AddServiceDefaults().
    • Vous ne devez pas conserver la configuration dans local.settings.json, à part le paramètre FUNCTIONS_WORKER_RUNTIME, qui doit rester « dotnet-isolated ». Une autre configuration doit être définie via le projet d’hôte d’application.
    • Vous devez supprimer les intégrations directes d’Application Insights. La surveillance dans Aspire est plutôt gérée par le biais de sa prise en charge d’OpenTelemetry.

L’exemple suivant montre un Program.cs minimum pour un projet d’hôte d’application :

var builder = DistributedApplication.CreateBuilder(args);

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject");

builder.Build().Run();

L’exemple suivant montre un Program.cs minimum pour un projet Functions utilisé dans Aspire :

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = FunctionsApplication.CreateBuilder(args);

builder.AddServiceDefaults();

builder.ConfigureFunctionsWebApplication();

builder.Build().Run();

Cela n’inclut pas la configuration par défaut d’Application Insights que vous voyez dans la plupart des autres exemples Program.cs de cet article. Au lieu de cela, l’intégration d’OpenTelemetry dans Aspire est configurée par le biais de l’appel builder.AddServiceDefaults().

Considérations et meilleures pratiques pour l’intégration de .NET Aspire

Tenez compte des points suivants lors de l’évaluation de .NET Aspire avec Azure Functions :

  • La prise en charge d’Azure Functions avec .NET Aspire est actuellement en préversion. Pendant la période de préversion, lorsque vous publiez la solution Aspire sur Azure, les projets Functions sont déployés en tant que ressources Azure Container Apps sans mise à l’échelle pilotée par les événements. La prise en charge d’Azure Functions n’est pas disponible pour les applications déployées dans ce mode.
  • La configuration du déclencheur et de la liaison via Aspire est actuellement limitée à des intégrations spécifiques. Pour plus d’informations, consultez Configuration de la connexion avec Aspire.
  • Votre Program.cs doit utiliser la version IHostApplicationBuilder du démarrage de l’instance hôte. Cela vous permet d’appeler builder.AddServiceDefaults() pour ajouter leservice par défaut .NET Aspire à votre projet Functions.
  • Aspire utilise OpenTelemetry pour la surveillance. Vous pouvez configurer Aspire pour exporter les données de télémétrie vers Azure Monitor via le projet de service par défaut. Dans de nombreux autres contextes Azure Functions, vous pouvez inclure l’intégration directe à Application Insights en inscrivant le service worker de télémétrie. Cela n’est pas recommandé dans Aspire et peut entraîner des erreurs d’exécution avec la version 2.22.0 de Microsoft.ApplicationInsights.WorkerService. Vous devez supprimer toutes les intégrations directes d’Application Insights de votre projet Functions lors de l’utilisation d’Aspire.
  • Pour les projets Functions inscrits dans une orchestration Aspire, la plupart de la configuration de l’application doit provenir du projet d’hôte d’application Aspire. Vous devez généralement éviter de définir des éléments dans local.settings.json, autres que le paramètre FUNCTIONS_WORKER_RUNTIME. Si la même variable d’environnement est définie par local.settings.json et Aspire, le système utilise la version d’Aspire.
  • Ne configurez pas l’émulateur de stockage pour les connexions dans local.settings.json. De nombreux modèles de démarrage Functions incluent l’émulateur par défaut pour AzureWebJobsStorage. Toutefois, la configuration de l’émulateur peut inviter certains IDE à démarrer une version de l’émulateur qui peut entrer en conflit avec la version utilisée par Aspire.

Configuration de la connexion avec Aspire

Azure Functions nécessite une connexion de stockage hôte (AzureWebJobsStorage) pour plusieurs de ses comportements de base. Lorsque vous appelez AddAzureFunctionsProject<TProject>() dans votre projet d’hôte d’application, une connexion AzureWebJobsStorage par défaut est créée et fournie au projet Functions. Cette connexion par défaut utilise l’émulateur de stockage pour les exécutions de développement local et approvisionne automatiquement un compte de stockage lors du déploiement. Pour un contrôle supplémentaire, vous pouvez remplacer cette connexion en appelant .WithHostStorage() la ressource de projet Functions.

L’exemple suivant montre un Program.cs minimum pour un projet d’hôte d’application qui remplace le stockage hôte :

var builder = DistributedApplication.CreateBuilder(args);

var myHostStorage = builder.AddAzureStorage("myHostStorage");

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithHostStorage(myHostStorage);

builder.Build().Run();

Remarque

Lorsque Aspire approvisionne le stockage hôte en mode de publication, il crée par défaut des attributions de rôles pour les rôles Collaborateur de compte de stockage, Collaborateur aux données blob de stockage, Collaborateur aux données de file d’attente du stockage et Collaborateur aux données de table de stockage.

Vos déclencheurs et liaisons référencent les connexions par nom. Certaines intégrations Aspire sont activées pour les fournir via un appel à WithReference() la ressource de projet :

Intégration Aspire Notes
Objets blob Azure Lorsque Aspire approvisionne la ressource, il crée par défaut des attributions de rôle pour les rôles Collaborateur aux données Blob de stockage, Collaborateur aux données de file d’attente du stockage et Collaborateur aux données de table de stockage.
Files d’attente Azure Lorsque Aspire approvisionne la ressource, il crée par défaut des attributions de rôle pour les rôles Collaborateur aux données Blob de stockage, Collaborateur aux données de file d’attente du stockage et Collaborateur aux données de table de stockage.
Azure Event Hubs Lorsque Aspire approvisionne la ressource, elle crée par défaut une attribution de rôle à l’aide du rôle Propriétaire des données Azure Event Hubs.
Azure Service Bus Lorsque Aspire approvisionne la ressource, elle crée par défaut une attribution de rôle à l’aide du rôle Propriétaire des données Azure Service Bus.

L’exemple suivant montre un Program.cs minimum pour un projet d’hôte d’application qui configure un déclencheur de file d’attente. Dans cet exemple, le déclencheur de file d’attente correspondant a sa propriété Connection définie sur « MyQueueTriggerConnection ».

var builder = DistributedApplication.CreateBuilder(args);

var myAppStorage = builder.AddAzureStorage("myAppStorage").RunAsEmulator();
var queues = myAppStorage.AddQueues("queues");

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithReference(queues, "MyQueueTriggerConnection");

builder.Build().Run();

Pour d’autres intégrations, les appels à WithReference définissent la configuration de manière différente, la rendant disponible pour les intégrations clientes Aspire, mais pas pour les déclencheurs et les liaisons. Pour ces intégrations, vous devez appeler WithEnvironment() pour passer les informations de connexion pour le déclencheur ou la liaison à résoudre. L’exemple suivant montre comment définir la variable d’environnement « MyBindingConnection » pour une ressource qui expose une expression de chaîne de connexion :

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithEnvironment("MyBindingConnection", otherIntegration.Resource.ConnectionStringExpression);

Vous pouvez configurer à la fois WithReference() et WithEnvironment() si vous souhaitez qu’une connexion soit utilisée à la fois par les intégrations clientes Aspire et par le système de déclencheurs et de liaisons.

Pour certaines ressources, la structure d’une connexion peut être différente entre le moment où vous l’exécutez localement et lorsque vous la publiez sur Azure. Dans l’exemple précédent, otherIntegration peut être une ressource qui s’exécute en tant qu’émulateur de sorte que ConnectionStringExpression retourne une chaîne de connexion d’émulateur. Toutefois, lorsque la ressource est publiée, Aspire peut configurer une connexion basée sur l’identité et ConnectionStringExpression retournerait l’URI du service. Dans ce cas, pour configurer des connexions basées sur des identités pour Azure Functions, vous devrez peut-être fournir un autre nom de variable d’environnement. L’exemple suivant utilise builder.ExecutionContext.IsPublishMode pour ajouter conditionnellement le suffixe nécessaire :

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithEnvironment("MyBindingConnection" + (builder.ExecutionContext.IsPublishMode ? "__serviceUri" : ""), otherIntegration.Resource.ConnectionStringExpression);

Selon votre scénario, vous devrez peut-être également ajuster les autorisations qui seront affectées pour une connexion basée sur les identités. Vous pouvez utiliser la méthode ConfigureConstruct<T>() pour personnaliser la façon dont Aspire configure l’infrastructure lors de la publication de votre projet.

Consultez les pages de référence de chaque liaison pour plus d’informations sur les formats de connexion pris en charge et les autorisations requises par ces formats.

Débogage

Lors d’une exécution locale à l’aide de Visual Studio ou Visual Studio Code, vous pouvez déboguer votre projet de Worker isolé .NET normalement. Toutefois, il existe deux scénarios de débogage qui ne fonctionnent pas comme prévu.

Débogage distant avec Visual Studio

Étant donné que votre application de processus worker isolé s’exécute en dehors du runtime Functions, vous devez attacher le débogueur distant à un processus distinct. Pour en savoir plus sur le débogage à l’aide de Visual Studio, consultez Débogage à distance.

Débogage lors du ciblage du .NET Framework

Si votre projet isolé cible .NET Framework 4.8, l’étendue de la préversion actuelle nécessite d’effectuer des étapes manuelles pour activer le débogage. Ces étapes ne sont pas nécessaires si vous utilisez un autre cadre cible.

La première opération de votre application doit être un appel à FunctionsDebugger.Enable();. Cela se produit dans la méthode Main() avant d’initialiser une ressource HostBuilder. Votre fichier Program.cs doit ressembler à ceci :

using System;
using System.Diagnostics;
using Microsoft.Extensions.Hosting;
using Microsoft.Azure.Functions.Worker;
using NetFxWorker;

namespace MyDotnetFrameworkProject
{
    internal class Program
    {
        static void Main(string[] args)
        {
            FunctionsDebugger.Enable();

            var host = new HostBuilder()
                .ConfigureFunctionsWorkerDefaults()
                .Build();

            host.Run();
        }
    }
}

Ensuite, vous devez attacher manuellement le processus à l’aide d’un débogueur .NET Framework. Visual Studio ne le fait pas encore automatiquement pour les applications .NET Framework à processus worker isolé, et l'opération « Start Debugging » doit être évitée.

Dans le répertoire de votre projet (ou son répertoire de sortie de build), exécutez :

func host start --dotnet-isolated-debug

Cela démarre votre Worker, et le processus s’arrête avec le message suivant :

Azure Functions .NET Worker (PID: <process id>) initialized in debug mode. Waiting for debugger to attach...

<process id> est l’ID de votre processus Worker. Vous pouvez maintenant utiliser Visual Studio pour attacher manuellement le processus. Pour obtenir des instructions sur cette opération, consultez Comment attacher un débogueur à un processus en cours d’exécution.

Une fois le débogueur attaché, l’exécution du processus reprend et vous pourrez procéder au débogage.

Préversions de .NET

Avant une version en disponibilité générale, une version .NET peut être mise en production à l’état Préversion ou Mise en service. Pour en savoir plus sur ces états, reportez-vous à stratégie de support officiel .NET.

Bien qu'il soit possible de cibler une version donnée à partir d'un projet Functions local, les applications de fonction hébergées dans Azure peuvent ne pas disposer de cette version. Azure Functions ne peut être utilisé qu’avec les versions Préversion ou Mise en service indiquées dans cette section.

Actuellement, Azure Functions peut être utilisé avec les versions de .NET « Préversion » ou « Go-live » suivantes :

Système d’exploitation Version de la préversion de .NET
Windows .NET 9 Preview 61, 2
Linux .NET 9 RC21, 3

1 Pour cibler .NET 9, votre projet doit référencer les versions 2.x des packages principaux. Si vous utilisez Visual Studio, .NET 9 nécessite la version 17.12 ou ultérieure.

2 La prise en charge de Windows peut ne pas apparaître dans certains clients pendant la période de préversion.

3 .NET 9 n’est pas encore pris en charge sur la référence SKU Consommation flexible.

Reportez-vous à Versions prises en charge pour obtenir la liste des versions en disponibilité générale que vous pouvez utiliser.

Utilisation d’un Kit de développement logiciel (SDK) .NET en préversion

Pour utiliser Azure Functions avec une version de la préversion de .NET, vous devez mettre à jour votre projet en procédant comme suit :

  1. Installation de la version adéquate du Kit de développement logiciel (SDK) .NET dans votre développement
  2. Modification du paramètre TargetFramework dans votre fichier .csproj

Lors du déploiement sur votre application de fonction dans Azure, vous devez également vérifier que l’infrastructure est à la disposition de l’application. Pendant la période de préversion, des outils et expériences peuvent ne pas exposer la nouvelle version préliminaire en tant qu’option. Par exemple, si vous ne voyez pas la préversion dans le Portail Azure, vous pouvez utiliser l’API REST, les modèles Bicep ou Azure CLI pour configurer la version manuellement.

Pour les applications hébergées sur Windows, utilisez la commande Azure CLI suivante. Remplacez <groupName> par le nom de votre groupe de ressources, et remplacez <appName> par le nom de votre application de fonction. Remplacez <framework> par la chaîne de version appropriée, comme v8.0.

az functionapp config set -g <groupName> -n <appName> --net-framework-version <framework>

Considérations relatives à l’utilisation des versions de la préversion de .NET

Gardez ces considérations à l’esprit lors de l’utilisation de Functions avec des versions de la préversion de .NET :

  • Lorsque vous créez vos fonctions dans Visual Studio, vous devez utiliser Visual Studio Preview, qui prend en charge la création de projets Azure Functions avec des kits SDK en préversion .NET.

  • Vérifiez que vous disposez des derniers outils et modèles Functions. Pour mettre à jour vos outils :

    1. Accédez à Outils>Options, choisissez Azure Functions sous Projets et solutions.
    2. Sélectionnez Rechercher les mises à jour et installez les mises à jour comme indiqué.
  • Pendant une période de préversion, votre environnement de développement peut disposer d’une version plus récente de la préversion .NET que le service hébergé. Cela peut entraîner l’échec de votre application de fonction lors du déploiement. Pour résoudre ce problème, vous pouvez spécifier la version du kit SDK à utiliser dans global.json.

    1. Exécutez la commande dotnet --list-sdks et notez la préversion que vous utilisez actuellement pendant le développement local.
    2. Exécutez la commande dotnet new globaljson --sdk-version <SDK_VERSION> --force, où <SDK_VERSION> est la version que vous utilisez localement. Par exemple, dotnet new globaljson --sdk-version dotnet-sdk-8.0.100-preview.7.23376.3 --force oblige le système à utiliser le kit SDK .NET 8 préversion 7 lors de la génération de votre projet.

Remarque

En raison du chargement juste-à-temps des infrastructures en préversion, les temps de démarrage à froid des applications de fonctions s’exécutant sur Windows peuvent être plus élevés que ceux des versions en disponibilité générale antérieures.

Étapes suivantes