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-process4 |
---|---|---|
Functions 4.x1 | .NET 9.0 .NET 8.0 .NET Framework 4.82 |
.NET 8.0 |
Functions 1.x3 | n/a | .NET Framework 4.8 |
1 .NET 6 était précédemment pris en charge sur les deux modèles, mais a atteint la fin du support officiel le 12 novembre 2024. .NET 7 était précédemment pris en charge sur le modèle de Worker isolé, mais il a atteint la fin du support officiel le 14 mai 2024.
2 Le processus de génération nécessite également le kit de développement logiciel (SDK) .NET.
3 La prise en charge de la version 1.x du runtime Azure Functions prendra 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.
4 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
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 ou version ultérieure, votre application doit référencer la version 2.0.0 ou ultérieure des deux packages.
Lors de la mise à jour vers les versions 2.x, notez les changements suivants :
- À compter de la version 2.0.0 de Microsoft.Azure.Functions.Worker.Sdk :
- Le kit SDK inclut des configurations par défaut pour les builds de conteneur SDK.
- Le kit SDK prend en charge
dotnet run
lorsqu’Azure Functions Core Tools est installé. Sous Windows, le Core Tools doit être installé par un mécanisme autre que NPM.
- À compter de la version 2.0.0 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 avecIHostApplicationBuilder
. 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 dansstring[]
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éfinissantIncludeEmptyEntriesInMessagePayload
surfalse
dans la configuration du serviceWorkerOptions
. - La classe
ILoggerExtensions
est renomméeFunctionsLoggerExtensions
. Le changement de nom évite une erreur d’appel ambiguë lors de l’utilisation deLogMetric()
sur une instanceILogger
. - Pour les applications qui utilisent
HttpResponseData
, la méthodeWriteAsJsonAsync()
ne définit plus le code d’état sur200 OK
. Dans la version 1.x, cela remplaçait d’autres codes d’erreur qui avaient été définis.
- Cette version ajoute la prise en charge de
- Les versions 2.x suppriment la prise en charge de .NET 5 TFM.
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://zcusa.951200.xyz/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 ouConfigureFunctionsWorkerDefaults()
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 appelerAddApplicationInsightsTelemetryWorkerService()
etConfigureFunctionsApplicationInsights()
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 :
Ajoutez une référence dans votre projet au package Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore, version 1.0.0 ou ultérieure.
Mettez à jour votre projet de façon à utiliser ces versions de package spécifiques :
- Microsoft.Azure.Functions.Worker.Sdk, version 1.11.0. ou version ultérieure
- Microsoft.Azure.Functions.Worker, version 1.16.0 ou ultérieure.
Dans votre fichier
Program.cs
, mettez à jour la configuration du générateur d’hôte pour appelerConfigureFunctionsWebApplication()
. Ceci remplaceConfigureFunctionsWorkerDefaults()
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();
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 unIActionResult
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.
Vous pouvez continuer à utiliser HttpRequestData
et HttpResponsedata
pendant l’utilisation de l’intégration ASP.NET, bien que nous recommandions d’utiliser HttpRequest
et IActionResult
à la place pour la plupart des applications. L’utilisation de HttpRequestData
/HttpResponseData
n’implique par la couche de sérialisation ASP.NET Core et s’appuie à la place sur la configuration générale de sérialisation du Worker pour l’application. Toutefois, quand l’intégration ASP.NET Core est activée, il est possible que vous deviez toujours ajouter la configuration. Le comportement par défaut à partir de ASP.NET Core consiste à interdire les E/S synchrones. Pour utiliser un sérialiseur personnalisé qui ne prend pas en charge les E/S asynchrones, comme NewtonsoftJsonObjectSerializer
, vous devez activer les E/S synchrones pour votre application en configurant les KestrelServerOptions
.
L’exemple suivant montre comment configurer JSON.NET (Newtonsoft.Json
) et le package NuGet Microsoft.AspNetCore.Mvc.NewtonsoftJson pour la sérialisation en utilisant cette approche :
using Microsoft.AspNetCore.Server.Kestrel.Core;
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();
// Only needed if using HttpRequestData/HttpResponseData and a serializer that doesn't support asynchronous IO
// services.Configure<KestrelServerOptions>(options => options.AllowSynchronousIO = true);
})
.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 :
- Microsoft.Azure.Functions.Worker.ApplicationInsights, version 1.0.0 ou ultérieure.
- Microsoft.ApplicationInsights.WorkerService.
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 :
- Mettez à niveau Microsoft.Azure.Functions.Worker vers la version 1.19.0 ou ultérieure.
- Mettez à niveau Microsoft.Azure.Functions.Worker.Sdk vers la version 1.16.4 ou une version ultérieure.
- 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 :
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.
Affectez la valeur
WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED
au paramètre d’application1
, 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.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 quev8.0
, en fonction de votre version cible de .NET.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 :
- Visual Studio : déploiement manuel simple pendant le développement.
- Visual Studio Code : déploiement manuel simple pendant le développement.
- Azure Functions Core Tools : déployer le fichier projet à partir de la ligne de commande.
- Déploiement continu : utile pour la maintenance continue, fréquemment vers un emplacement intermédiaire.
- Modèles de déploiement : vous pouvez utiliser des modèles ARM ou des fichiers Bicep pour automatiser les déploiements de packages.
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 :
- FUNCTIONS_Worker_RUNTIME doit être défini sur la valeur
dotnet-isolated
. - netFrameworkVersion doit être défini sur la version souhaitée.
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 appelantAddAzureFunctionsProject<TProject>()
sur votreIDistributedApplicationBuilder
. Cette méthode est utilisée au lieu deAddProject<TProject>()
que vous utilisez pour d’autres types de projet. Si vous utilisez uniquementAddProject<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 versionIHostApplicationBuilder
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
dansProgram.cs
, vous devez également inclure un appel àbuilder.AddServiceDefaults()
. - Vous ne devez pas conserver la configuration dans
local.settings.json
, à part le paramètreFUNCTIONS_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.
- 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 à
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 versionIHostApplicationBuilder
du démarrage de l’instance hôte. Cela vous permet d’appelerbuilder.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ètreFUNCTIONS_WORKER_RUNTIME
. Si la même variable d’environnement est définie parlocal.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 pourAzureWebJobsStorage
. 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 celui où 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, vus devez 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...
Où <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.
Azure Functions ne fonctionne actuellement pas avec les versions « Préversion » ou « Mise en service » .NET. 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 :
- Installation de la version adéquate du Kit de développement logiciel (SDK) .NET dans votre développement
- 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 :
- Accédez à Outils>Options, choisissez Azure Functions sous Projets et solutions.
- 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
.- Exécutez la commande
dotnet --list-sdks
et notez la préversion que vous utilisez actuellement pendant le développement local. - 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.
- Exécutez la commande
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.