Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Ce guide vous guide tout au long de la migration de votre application .NET Durable Functions du modèle in-process vers le modèle worker isolé. Le modèle in-process atteint la fin du support le 10 novembre 2026. Après cette date, aucune mise à jour de sécurité ni correctifs de bogues n’est fourni. Le modèle worker isolé vous offre également un contrôle de processus complet, une injection de dépendances de .NET standard et un accès aux dernières fonctionnalités de la plateforme.
Avertissement
La prise en charge du modèle in-process se termine le 10 novembre 2026. Nous vous recommandons de migrer maintenant. Pour plus d’informations sur le modèle worker isolé, consultez vue d’ensemble du processus worker isolé .NET.
Liste des éléments à vérifier pour la migration
Utilisez la liste de contrôle suivante pour suivre votre progression à chaque étape de migration :
| Étape | Section |
|---|---|
| 1. Vérifier les prérequis | Conditions préalables |
| 2. Mettre à jour le fichier projet | Mettre à jour le fichier projet |
| 3. Ajouter Program.cs | Ajouter le fichier Program.cs |
| 4. Mettre à jour les références de package | Mettre à jour les références de package |
| 5. Mettre à jour le code de fonction | Mettre à jour le code de fonction |
| 6. Mettre à jour local.settings.json | Mettre à jour local.settings.json |
| 7. Tester localement | Tester localement |
| 8. Déployer sur Azure | Déployer dans Azure |
Prerequisites
- Azure Functions Core Tools v4.x ou version ultérieure
- .NET sdk 8.0 (ou votre version .NET cible)
- Visual Studio 2022 ou VS Code avec Azure Functions extension
Identifier les applications à migrer (facultatif)
Si vous ne savez pas quelles applications utilisent toujours le modèle in-process, exécutez ce script Azure PowerShell :
$FunctionApps = Get-AzFunctionApp
$AppInfo = @{}
foreach ($App in $FunctionApps)
{
if ($App.Runtime -eq 'dotnet')
{
$AppInfo.Add($App.Name, $App.Runtime)
}
}
$AppInfo
Les applications qui s’affichent dotnet en tant que runtime utilisent le modèle in-process. Applications qui montrent dotnet-isolated utilisent déjà le modèle worker isolé.
Mettre à jour le fichier projet
Avant (en cours)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.1" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="2.13.0" />
</ItemGroup>
</Project>
Après (travailleur isolé)
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
<OutputType>Exe</OutputType>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<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.17.2" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore" Version="1.2.1" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.DurableTask" Version="1.14.1" />
<PackageReference Include="Microsoft.ApplicationInsights.WorkerService" Version="2.22.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.ApplicationInsights" Version="1.2.0" />
</ItemGroup>
<ItemGroup>
<Using Include="System.Threading.ExecutionContext" Alias="ExecutionContext"/>
</ItemGroup>
</Project>
Les principales modifications passent à un type de sortie exécutable et remplacent tous les packages Microsoft.Azure.WebJobs.* par leurs équivalents Microsoft.Azure.Functions.Worker.*.
Ajouter Program.cs
Le modèle d'ouvrier isolé nécessite un point d'entrée Program.cs. Créez ce fichier à la racine de votre projet. Si vous avez une FunctionsStartup classe dans Startup.cs, déplacez ces enregistrements de service dans le bloc ConfigureServices et supprimez Startup.cs.
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices(services => {
services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();
// Add your custom services here (previously in FunctionsStartup)
// services.AddSingleton<IMyService, MyService>();
})
.Build();
host.Run();
Mettre à jour les références de package
Mappage de paquet Durable Functions
| Paquet en cours de traitement | Paquet de travailleur isolé |
|---|---|
Microsoft.Azure.WebJobs.Extensions.DurableTask |
Microsoft.Azure.Functions.Worker.Extensions.DurableTask |
Microsoft.DurableTask.SqlServer.AzureFunctions |
Microsoft.Azure.Functions.Worker.Extensions.DurableTask.SqlServer |
Microsoft.Azure.DurableTask.Netherite.AzureFunctions |
Microsoft.Azure.Functions.Worker.Extensions.DurableTask.Netherite |
Mappage commun des packages d’extension
| En cours | Travailleur isolé |
|---|---|
Microsoft.Azure.WebJobs.Extensions.Storage |
Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs, .Queues, .Tables |
Microsoft.Azure.WebJobs.Extensions.CosmosDB |
Microsoft.Azure.Functions.Worker.Extensions.CosmosDB |
Microsoft.Azure.WebJobs.Extensions.ServiceBus |
Microsoft.Azure.Functions.Worker.Extensions.ServiceBus |
Microsoft.Azure.WebJobs.Extensions.EventHubs |
Microsoft.Azure.Functions.Worker.Extensions.EventHubs |
Microsoft.Azure.WebJobs.Extensions.EventGrid |
Microsoft.Azure.Functions.Worker.Extensions.EventGrid |
Important
Supprimez les références aux espaces de noms Microsoft.Azure.WebJobs.* et Microsoft.Azure.Functions.Extensions de votre projet.
Mettre à jour le code de fonction
Cette section traite des modifications de code pour chaque type de Durable Functions. Accédez à la section pour les types de fonctions que votre application utilise :
- Modifications de l’espace de noms
- Fonctions d’orchestrateur
- Fonctions d’activité
- Fonctions clientes
- Stratégies de nouvelle tentative (si utilisées)
- Fonctions d’entité (si utilisées)
Pour obtenir un mappage d’API par API complet, consultez la référence de l’API.
Modifications de l’espace de noms
// Before (In-Process)
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.DurableTask;
using Microsoft.Azure.WebJobs.Extensions.Http;
// After (Isolated Worker)
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Http;
using Microsoft.DurableTask;
using Microsoft.DurableTask.Client;
using Microsoft.DurableTask.Entities;
Modifications de l’attribut de fonction
// Before (In-Process)
[FunctionName("MyOrchestrator")]
// After (Isolated Worker)
[Function(nameof(MyOrchestrator))]
Modifications de la fonction d'orchestration
Avant (En cours) :
[FunctionName("OrderOrchestrator")]
public static async Task<OrderResult> RunOrchestrator(
[OrchestrationTrigger] IDurableOrchestrationContext context,
ILogger log)
{
var order = context.GetInput<Order>();
await context.CallActivityAsync("ValidateOrder", order);
await context.CallActivityAsync("ProcessPayment", order.Payment);
await context.CallActivityAsync("ShipOrder", order);
return new OrderResult { Success = true };
}
Après (Travailleur isolé) :
[Function(nameof(OrderOrchestrator))]
public static async Task<OrderResult> OrderOrchestrator(
[OrchestrationTrigger] TaskOrchestrationContext context)
{
ILogger logger = context.CreateReplaySafeLogger(nameof(OrderOrchestrator));
var order = context.GetInput<Order>();
await context.CallActivityAsync("ValidateOrder", order);
await context.CallActivityAsync("ProcessPayment", order.Payment);
await context.CallActivityAsync("ShipOrder", order);
return new OrderResult { Success = true };
}
Principales différences
| Aspect | En cours | Travailleur isolé |
|---|---|---|
| Type de contexte | IDurableOrchestrationContext |
TaskOrchestrationContext |
| Logger | Paramètre ILogger |
context.CreateReplaySafeLogger() |
| Caractéristique | [FunctionName] |
[Function] |
Modifications de la fonction d’activité
Avant (En cours) :
[FunctionName("ValidateOrder")]
public static bool ValidateOrder(
[ActivityTrigger] Order order,
ILogger log)
{
log.LogInformation("Validating order {OrderId}", order.Id);
return order.Items.Any() && order.TotalAmount > 0;
}
Après (Travailleur isolé) :
[Function(nameof(ValidateOrder))]
public static bool ValidateOrder(
[ActivityTrigger] Order order,
FunctionContext executionContext)
{
ILogger logger = executionContext.GetLogger(nameof(ValidateOrder));
logger.LogInformation("Validating order {OrderId}", order.Id);
return order.Items.Any() && order.TotalAmount > 0;
}
Modifications de la fonction cliente
Avant (En cours) :
[FunctionName("StartOrder")]
public static async Task<IActionResult> StartOrder(
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req,
[DurableClient] IDurableOrchestrationClient client,
ILogger log)
{
var order = await req.ReadFromJsonAsync<Order>();
string instanceId = await client.StartNewAsync("OrderOrchestrator", order);
return client.CreateCheckStatusResponse(req, instanceId);
}
Après (Travailleur isolé) :
[Function("StartOrder")]
public static async Task<HttpResponseData> StartOrder(
[HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequestData req,
[DurableClient] DurableTaskClient client,
FunctionContext executionContext)
{
ILogger logger = executionContext.GetLogger("StartOrder");
var order = await req.ReadFromJsonAsync<Order>();
string instanceId = await client.ScheduleNewOrchestrationInstanceAsync(
nameof(OrderOrchestrator),
order
);
return await client.CreateCheckStatusResponseAsync(req, instanceId);
}
Modifications de type client
| En cours | Travailleur isolé |
|---|---|
IDurableOrchestrationClient |
DurableTaskClient |
StartNewAsync() |
ScheduleNewOrchestrationInstanceAsync() |
CreateCheckStatusResponse() |
CreateCheckStatusResponseAsync() |
HttpRequest / IActionResult |
HttpRequestData / HttpResponseData |
Nouvelles tentatives de modification de la stratégie
In-process utilise RetryOptions avec CallActivityWithRetryAsync. Le travailleur isolé utilise TaskOptions avec la norme CallActivityAsync.
Avant (En cours) :
var retryOptions = new RetryOptions(
firstRetryInterval: TimeSpan.FromSeconds(5),
maxNumberOfAttempts: 3);
string result = await context.CallActivityWithRetryAsync<string>(
"MyActivity", retryOptions, input);
Après (Travailleur isolé) :
var retryOptions = new TaskOptions(
new TaskRetryOptions(new RetryPolicy(
maxNumberOfAttempts: 3,
firstRetryInterval: TimeSpan.FromSeconds(5))));
string result = await context.CallActivityAsync<string>(
"MyActivity", input, retryOptions);
Modifications de la fonction d’entité
Avant (En cours) :
[FunctionName(nameof(Counter))]
public static void Counter([EntityTrigger] IDurableEntityContext ctx)
{
switch (ctx.OperationName.ToLowerInvariant())
{
case "add":
ctx.SetState(ctx.GetState<int>() + ctx.GetInput<int>());
break;
case "get":
ctx.Return(ctx.GetState<int>());
break;
}
}
Après (Travailleur isolé) :
[Function(nameof(Counter))]
public static Task Counter([EntityTrigger] TaskEntityDispatcher dispatcher)
{
return dispatcher.DispatchAsync<CounterEntity>();
}
public class CounterEntity
{
public int Value { get; set; }
public void Add(int amount) => Value += amount;
public int Get() => Value;
}
Changements de comportement cassants
Passez en revue ces modifications avant de tester votre application migrée. Pour obtenir le mappage d’API par API complet, consultez la référence de l’API.
Avertissement
La sérialisation par défaut a changé : le worker isolé utilise System.Text.Json par défaut au lieu de Newtonsoft.Json. Si vos orchestrations passent des objets complexes, testez soigneusement la sérialisation. Consultez les différences de sérialisation JSON pour connaître les options de configuration.
Avertissement
Modification par défaut de ContinueAsNew : le preserveUnprocessedEvents paramètre par défaut est passé de false (2.x) à true (isolé). Si votre orchestration utilise ContinueAsNew et s’appuie sur le fait que les événements non traités soient ignorés, transmettez preserveUnprocessedEvents: false explicitement.
Note
Changement par défaut de RestartAsync : le restartWithNewInstanceId paramètre par défaut est passé de true (2.x) à false (isolé). Si votre code appelle RestartAsync et dépend d’un nouvel ID d’instance généré, passez restartWithNewInstanceId: trueexplicitement .
Autres changements notables :
-
Les proxys d’entité ont été supprimés
CreateEntityProxy<T>n'est pas disponible. UtilisezEntities.CallEntityAsyncouEntities.SignalEntityAsyncdirectement. -
Opérations inter-tâches-hub supprimées : les surcharges acceptées
taskHubName/connectionNamene sont pas disponibles. Seules les opérations sur des hubs de tâches identiques sont prises en charge. -
Historique de l’orchestration déplacé :
DurableOrchestrationStatus.Historyn'est plus inclus dans l'objet d'état. UtilisezDurableTaskClient.GetOrchestrationHistoryAsync.
Mettre à jour local.settings.json
Le changement principal est la configuration de FUNCTIONS_WORKER_RUNTIME, passant de dotnet à dotnet-isolated.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
}
}
Note
Votre configuration back-end de stockage (stockage Azure, MSSQL, Netherite ou Durable Task Scheduler) n’est pas modifiée par la migration. Conservez vos paramètres de stockage existants.
Tester localement
Exécutez votre application de fonction localement et vérifiez que toutes les orchestrations, activités et entités fonctionnent correctement.
func start
Vérifier le fonctionnement
Testez les scénarios suivants, le cas échéant :
- Démarrer une orchestration avec un déclencheur HTTP
- Surveiller l’état de l’orchestration
- Vérifier l’ordre d’exécution de l’activité
- Tester les opérations d’entité le cas échéant
- Vérifier la télémétrie de Application Insights
Déployer sur Azure
Recommandé : Utiliser des slots de déploiement
Utilisez des emplacements de déploiement pour réduire les temps d’arrêt :
- Créez un emplacement de mise en scène pour votre application de fonction.
-
Mettre à jour la configuration de l’espace de mise en scène :
- Affectez la valeur
FUNCTIONS_WORKER_RUNTIMEàdotnet-isolated. - Mettez à jour la version de la pile .NET si nécessaire.
- Affectez la valeur
- Déployez le code migré sur le slot intermédiaire.
- Testez soigneusement dans l’emplacement de préproduction.
- Effectuez un échange d’emplacement pour déplacer les modifications vers la production.
Mettre à jour les paramètres de l’application
Dans le portail Azure ou via l’interface CLI :
az functionapp config appsettings set \
--name <FUNCTION_APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--settings FUNCTIONS_WORKER_RUNTIME=dotnet-isolated
Mettre à jour la configuration de la pile
Si vous ciblez une autre version de .NET :
az functionapp config set \
--name <FUNCTION_APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--net-framework-version v8.0
Problèmes courants de migration
Problème : erreurs de chargement d’assembly
Symptôme:Could not load file or assembly Erreurs.
Solution : Veillez à supprimer toutes les références de paquet Microsoft.Azure.WebJobs.* et à les remplacer par des équivalents de travailleur isolés.
Problème : attribut de liaison introuvable
Symptôme:The type or namespace 'QueueTrigger' could not be found
Solution: Ajoutez le package d’extension approprié et mettez à jour à l’aide d’instructions :
// Add using statement
using Microsoft.Azure.Functions.Worker;
// Install package
// dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues
Problème : IDurableOrchestrationContext introuvable
Symptôme:The type or namespace 'IDurableOrchestrationContext' could not be found
Solution: Remplacez par TaskOrchestrationContext:
using Microsoft.DurableTask;
[Function(nameof(MyOrchestrator))]
public static async Task MyOrchestrator([OrchestrationTrigger] TaskOrchestrationContext context)
{
// ...
}
Problème : différences de sérialisation JSON
Symptôme: Erreurs de sérialisation ou formats de données inattendus
Solution: Le modèle isolé utilise System.Text.Json par défaut. Configurer la sérialisation dans Program.cs:
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices(services => {
services.Configure<JsonSerializerOptions>(options => {
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
})
.Build();
Pour utiliser Newtonsoft.Json à la place :
services.Configure<WorkerOptions>(options => {
options.Serializer = new NewtonsoftJsonObjectSerializer();
});
Problème : Migration des paramètres de sérialisation personnalisés
Symptôme : Vous avez utilisé IMessageSerializerSettingsFactory dans un modèle en cours et avez besoin de l’équivalent dans un travailleur isolé.
Solution: Configurez le sérialiseur de niveau de travailleur dans Program.cs. Pour plus d’informations, consultez la section behavioral changes de la référence d’API et Sérialisation et persistance dans Durable Functions.
Pour utiliser Newtonsoft.Json avec des paramètres personnalisés :
// Program.cs
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices(services =>
{
services.Configure<WorkerOptions>(options =>
{
var settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.None,
DateFormatHandling = DateFormatHandling.IsoDateFormat,
};
options.Serializer = new NewtonsoftJsonObjectSerializer(settings);
});
})
.Build();
Note
Cette approche nécessite les packages NuGet Newtonsoft.Json et Azure.Core.Serialization.
Liste de contrôle
Utilisez cette liste de contrôle pour garantir une migration complète :
- Fichier projet mis à jour avec
<OutputType>Exe</OutputType> - Remplacement de
Microsoft.NET.Sdk.Functionspar des packages de worker - Remplacé
Microsoft.Azure.WebJobs.Extensions.DurableTaskpar un package isolé - Créé
Program.csavec la configuration de l’hôte - Classe supprimée
FunctionsStartup(le cas échéant) - Mise à jour de tous
[FunctionName]vers[Function] - Remplacé par
IDurableOrchestrationContextTaskOrchestrationContext - Remplacé par
IDurableOrchestrationClientDurableTaskClient - Mise à jour de la journalisation pour utiliser DI ou
FunctionContext - Mise à jour de
local.settings.jsonavec le runtimedotnet-isolated - Suppression de toutes les instructions utilisant
Microsoft.Azure.WebJobs.* - Ajout des instructions using pour
Microsoft.Azure.Functions.Worker - **
Remplacé
CreateEntityProxy<T>par des appels directsCallEntityAsync/SignalEntityAsync - Remplacement des surcharges d’opérations cross-task-hub (si utilisées)
- Remplacement des appels par lots
GetStatusAsync/PurgeInstanceHistoryAsyncbasés sur l’ID par des appels individuels ou basés sur des filtres - Accès migré
DurableOrchestrationStatus.HistoryversGetOrchestrationHistoryAsync - Mise à jour des paramètres du constructeur de l’entité
DispatchAsyncpour utiliser DI - Test de toutes les fonctions localement
- Déploiement sur l’emplacement de préproduction et vérification
- Passage en production
Étapes suivantes
- Mappage d’API de processus en workers isolés : référence d’API complète pour votre migration
- Vue d’ensemble de Durable Functions pour worker isolé .NET
- Guide des versions et de migration de Durable Functions
Contenu connexe
- Guide de migration Microsoft official (tous les Azure Functions)
- Vue d’ensemble du processus Worker isolé .NET
- Différences du modèle de worker isolé
- Sérialisation et persistance dans Durable Functions
- Déploiement de temps d’arrêt zéro pour Durable Functions
- Configurer le planificateur de tâches durables