Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Dieses Handbuch führt Sie durch die Migration Ihrer .NET Durable Functions-App vom In-Process-Modell zum isolierten Workermodell. Die Unterstützung für das In-Process-Modell endet am 10. November 2026. Nach diesem Datum werden keine Sicherheitsupdates oder Fehlerbehebungen bereitgestellt. Mit dem isolierten Arbeitsmodell erhalten Sie außerdem vollständige Prozesskontrolle, Standard-.NET Abhängigkeitsinjektion und Zugriff auf die neuesten Plattformfeatures.
Warnung
Die Unterstützung für das In-Process-Modell endet am 10. November 2026. Es wird empfohlen, jetzt zu migrieren. Hintergrundinformationen zum isolierten Arbeitsmodell finden Sie unter .NET Übersicht über isolierten Arbeitsprozess.
Migrationscheckliste
Verwenden Sie die folgende Checkliste, um den Fortschritt in jedem Migrationsschritt nachzuverfolgen:
| Step | Abschnitt |
|---|---|
| 1. Überprüfen der Voraussetzungen | Voraussetzungen |
| 2. Aktualisieren der Projektdatei | Aktualisieren der Projektdatei |
| 3. Hinzufügen von Program.cs | Hinzufügen von Program.cs |
| 4. Aktualisieren von Paketreferenzen | Aktualisieren von Paketverweise |
| 5. Funktionscode aktualisieren | Funktionscode aktualisieren |
| 6. Aktualisieren Sie die local.settings.json | Aktualisieren von local.settings.json |
| 7. Lokal testen | Lokal testen |
| 8. Bereitstellen für Azure | Deploy to Azure |
Voraussetzungen
- Azure Functions Core Tools v4.x oder höher
- .NET 8.0 SDK (oder Die Zielversion .NET)
- Visual Studio 2022 oder VS-Code mit Azure Functions Erweiterung
Identifizieren von Zu migrierenden Apps (optional)
Wenn Sie nicht sicher sind, welche Apps weiterhin das In-Process-Modell verwenden, führen Sie dieses Azure PowerShell Skript aus:
$FunctionApps = Get-AzFunctionApp
$AppInfo = @{}
foreach ($App in $FunctionApps)
{
if ($App.Runtime -eq 'dotnet')
{
$AppInfo.Add($App.Name, $App.Runtime)
}
}
$AppInfo
Apps, die dotnet als Laufzeit verwenden, nutzen das In-Process-Modell. Apps, die dotnet-isolated das isolierte Workermodell bereits verwenden.
Aktualisieren der Projektdatei
Bevor (in-process)
<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>
Nach (isolierter Mitarbeiter)
<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>
Die wichtigsten Änderungen wechseln zu einem ausführbaren Ausgabetyp und ersetzen alle Microsoft.Azure.WebJobs.*-Pakete durch ihre Microsoft.Azure.Functions.Worker.* Entsprechungen.
Hinzufügen von Program.cs
Für das isolierte Arbeitsmodell ist ein Program.cs Eingangspunkt erforderlich. Erstellen Sie diese Datei im Projektstamm. Wenn Sie eine FunctionsStartup-Klasse in Startup.cs haben, verschieben Sie die Dienstregistrierungen in den ConfigureServices-Block und löschen Sie 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();
Aktualisieren von Paketverweise
Durable Functions Paketabbildung
| In-Process-Paket | Isoliertes Worker-Paket |
|---|---|
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 |
Allgemeines Mapping für Erweiterungspakete
| In Bearbeitung | Eingeschlossener Mitarbeiter |
|---|---|
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 |
Von Bedeutung
Entfernen Sie alle Verweise auf Microsoft.Azure.WebJobs.* Namespaces und Microsoft.Azure.Functions.Extensions aus Ihrem Projekt.
Funktionscode aktualisieren
In diesem Abschnitt werden die Codeänderungen für jeden Durable Functions Typ behandelt. Springen Sie zu dem Abschnitt für die Funktionstypen, die Ihre App verwendet:
- Namespaceänderungen
- Orchestratorfunktionen
- Aktivitätsfunktionen
- Clientfunktionen
- Wiederholungsrichtlinien (sofern verwendet)
- Entitätsfunktionen (sofern verwendet)
Eine vollständige API-nach-API-Zuordnung finden Sie in der API-Referenz.
Namespaceänderungen
// 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;
Funktionsattributeänderungen
// Before (In-Process)
[FunctionName("MyOrchestrator")]
// After (Isolated Worker)
[Function(nameof(MyOrchestrator))]
Orchestrator-Funktionsänderungen
Vorher (In-Prozess):
[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 };
}
Nach (Isolierter Arbeiter):
[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 };
}
Wichtige Unterschiede
| Aspekt | In Bearbeitung | Isolierter Worker |
|---|---|---|
| Kontexttyp | IDurableOrchestrationContext |
TaskOrchestrationContext |
| Logger |
ILogger Parameter |
context.CreateReplaySafeLogger() |
| Merkmal | [FunctionName] |
[Function] |
Änderungen der Aktivitätsfunktion
Vorher (In-Prozess):
[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;
}
Nach (Isolierter Arbeiter):
[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;
}
Clientfunktionsänderungen
Vorher (In-Prozess):
[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);
}
Nach (Isolierter Arbeiter):
[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);
}
Clienttypänderungen
| In Bearbeitung | Eingeschlossener Mitarbeiter |
|---|---|
IDurableOrchestrationClient |
DurableTaskClient |
StartNewAsync() |
ScheduleNewOrchestrationInstanceAsync() |
CreateCheckStatusResponse() |
CreateCheckStatusResponseAsync() |
HttpRequest / IActionResult |
HttpRequestData / HttpResponseData |
Änderungen der Wiederholungsrichtlinie
In-Process verwendet RetryOptions mit CallActivityWithRetryAsync. Der isolierte Worker verwendet TaskOptions mit dem Standard CallActivityAsync.
Vorher (In-Prozess):
var retryOptions = new RetryOptions(
firstRetryInterval: TimeSpan.FromSeconds(5),
maxNumberOfAttempts: 3);
string result = await context.CallActivityWithRetryAsync<string>(
"MyActivity", retryOptions, input);
Nach (Isolierter Arbeiter):
var retryOptions = new TaskOptions(
new TaskRetryOptions(new RetryPolicy(
maxNumberOfAttempts: 3,
firstRetryInterval: TimeSpan.FromSeconds(5))));
string result = await context.CallActivityAsync<string>(
"MyActivity", input, retryOptions);
Änderungen der Entitätsfunktion
Vorher (In-Prozess):
[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;
}
}
Nach (Isolierter Arbeiter):
[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;
}
Unterbrechen von Verhaltensänderungen
Überprüfen Sie diese Änderungen, bevor Sie Ihre migrierte App testen. Die vollständige API-nach-API-Zuordnung finden Sie in der API-Referenz.
Warnung
Die Serialisierung wurde standardmäßig geändert: Der isolierte Worker verwendet System.Text.Json standardmäßig anstelle von Newtonsoft.Json. Wenn Ihre Orchestrierungen komplexe Objekte weitergeben, testen Sie die Serialisierung sorgfältig. Siehe JSON-Serialisierungsunterschiede für Konfigurationsoptionen.
Warnung
ContinueAsNew-Standardänderung: Der Standardwert des Parameters preserveUnprocessedEvents wurde von false (2.x) in true (isoliert) geändert. Wenn Ihre Orchestrierung ContinueAsNew verwendet und davon abhängig ist, dass nicht verarbeitete Ereignisse verworfen werden, übergeben Sie explizit preserveUnprocessedEvents: false.
Hinweis
RestartAsync-Standardänderung: Der restartWithNewInstanceId Parameterstandard wurde von true (2.x) in false (isoliert) geändert. Wenn Ihr Code RestartAsync aufruft und von einer neuen, generierten Instanz-ID abhängt, übergeben Sie restartWithNewInstanceId: true explizit.
Weitere wichtige Änderungen:
-
Entitätsproxys entfernt –
CreateEntityProxy<T>ist nicht verfügbar. Verwenden SieEntities.CallEntityAsyncoderEntities.SignalEntityAsyncdirekt. -
Auftragübergreifende Vorgänge wurden entfernt – Überladungen, die
taskHubName/connectionNameakzeptierten, sind nicht verfügbar. Es werden nur Vorgänge desselben Task-Hubs unterstützt. -
Der Orchestrierungsverlauf wurde verschoben –
DurableOrchestrationStatus.Historyist nicht mehr auf dem Statusobjekt. Verwenden SieDurableTaskClient.GetOrchestrationHistoryAsync.
Aktualisieren von local.settings.json
Die Schlüsseländerung ist das Setzen von FUNCTIONS_WORKER_RUNTIME von dotnet auf dotnet-isolated.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
}
}
Hinweis
Ihre Speicher-Back-End-Konfiguration (Azure Storage, MSSQL, Netherite oder Durable Task Scheduler) ist von der Migration unverändert. Behalten Sie Ihre vorhandenen Speichereinstellungen bei.
Lokales Testen
Führen Sie Ihre Funktions-App lokal aus und prüfen Sie, dass alle Orchestrierungen, Aktivitäten und Entitäten korrekt funktionieren.
func start
Überprüfen der Funktionalität
Testen Sie die folgenden Szenarien, falls zutreffend:
- Starten einer Orchestrierung mit einem HTTP-Trigger
- Überwachen des Orchestrierungsstatus
- Überprüfen der Ausführungsreihenfolge der Aktivität
- Testen von Entitätsvorgängen, falls zutreffend
- Überprüfen Sie die Telemetrie von Application Insights
In Azure bereitstellen
Empfohlen: Verwenden von Bereitstellungsplätzen
Verwenden Sie Bereitstellungsplätze, um Ausfallzeiten zu minimieren:
- Erstellen Sie einen Staging-Slot für Ihre Funktions-App.
-
Konfiguration des Stagingplatzes aktualisieren:
- Setzen Sie
FUNCTIONS_WORKER_RUNTIMEaufdotnet-isolated. - Aktualisieren Sie die .NET-Stackversion falls erforderlich.
- Setzen Sie
- Stellen Sie migrierten Code im Staging-Slot bereit.
- Testen Sie gründlich im Stagingslot.
- Durchführen eines Slottauschs um Änderungen in die Produktion zu übertragen.
Aktualisieren von Anwendungseinstellungen
Im Azure Portal oder über CLI:
az functionapp config appsettings set \
--name <FUNCTION_APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--settings FUNCTIONS_WORKER_RUNTIME=dotnet-isolated
Aktualisierung der Stapelkonfiguration
Wenn sie auf eine andere .NET Version ausgerichtet sind:
az functionapp config set \
--name <FUNCTION_APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--net-framework-version v8.0
Häufige Probleme bei der Migration
Problem: Assemblyladefehler
Symptom:Could not load file or assembly Fehler.
Lösung: Stellen Sie sicher, dass Sie alle Microsoft.Azure.WebJobs.*-Paketverweise entfernen und durch isolierte Workerentsprechungen ersetzen.
Problem: Das Bindungsattribut wurde nicht gefunden.
Symptom:The type or namespace 'QueueTrigger' could not be found
Lösung: Fügen Sie das entsprechende Erweiterungspaket hinzu, und aktualisieren Sie mithilfe von Anweisungen:
// Add using statement
using Microsoft.Azure.Functions.Worker;
// Install package
// dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues
Problem: IDurableOrchestrationContext nicht gefunden
Symptom:The type or namespace 'IDurableOrchestrationContext' could not be found
Lösung: Ersetzen durch TaskOrchestrationContext:
using Microsoft.DurableTask;
[Function(nameof(MyOrchestrator))]
public static async Task MyOrchestrator([OrchestrationTrigger] TaskOrchestrationContext context)
{
// ...
}
Problem: Unterschiede bei der JSON-Serialisierung
Symptom: Serialisierungsfehler oder unerwartete Datenformate
Lösung: Das isolierte Modell verwendet System.Text.Json standardmäßig. Serialisierung konfigurieren in Program.cs:
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices(services => {
services.Configure<JsonSerializerOptions>(options => {
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
})
.Build();
So verwenden Sie stattdessen Newtonsoft.Json:
services.Configure<WorkerOptions>(options => {
options.Serializer = new NewtonsoftJsonObjectSerializer();
});
Problem: Migrieren von benutzerdefinierten Serialisierungseinstellungen
Symptom: Sie haben das In-Process-Modell verwendet IMessageSerializerSettingsFactory und benötigen das Äquivalent in isolierten Workern.
Lösung: Konfigurieren Sie den Serialisierer auf Arbeitsebene in Program.cs. Ausführliche Informationen finden Sie im Abschnitt behavioral changes der API-Referenz und Serialisierung und Persistenz in Durable Functions.
So verwenden Sie Newtonsoft.Json mit benutzerdefinierten Einstellungen:
// 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();
Hinweis
Für diesen Ansatz sind die Newtonsoft.Json und Azure.Core.Serialization NuGet-Pakete erforderlich.
Prüfliste
Verwenden Sie diese Checkliste, um eine vollständige Migration sicherzustellen:
- Aktualisierte Projektdatei mit
<OutputType>Exe</OutputType> -
Microsoft.NET.Sdk.Functionsdurch Arbeitspakete ersetzt -
Microsoft.Azure.WebJobs.Extensions.DurableTaskdurch isoliertes Paket ersetzt - Erstellung von
Program.csmit Hostkonfiguration - Klasse
FunctionsStartupentfernt (sofern vorhanden) - Alle
[FunctionName]aktualisiert auf[Function] - Ersetzt
IDurableOrchestrationContextdurchTaskOrchestrationContext - Ersetzt
IDurableOrchestrationClientdurchDurableTaskClient - Aktualisierte Protokollierung für die Verwendung von DI oder
FunctionContext - Aktualisierung von
local.settings.jsonmitdotnet-isolated-Laufzeit - Alle
Microsoft.Azure.WebJobs.*Verwendungsanweisungen entfernt -
Microsoft.Azure.Functions.Worker-Verwendungsanweisungen hinzugefügt - Ersetzt
CreateEntityProxy<T>durch direkteCallEntityAsync/SignalEntityAsyncAnrufe - Ersetzte Cross-Task-Hub-Betriebsüberladungen (falls verwendet)
- Ersetzung von
GetStatusAsync/PurgeInstanceHistoryAsync-Batchaufrufen nach ID durch filterbasierte oder individuelle Aufrufe - Migrierter
DurableOrchestrationStatus.HistoryZugriff aufGetOrchestrationHistoryAsync - Aktualisierte Entitätskonstruktorparameter
DispatchAsyncfür die Verwendung von DI - Lokales Testen aller Funktionen
- Bereitgestellt für Staging-Slot und überprüft
- In die Produktion überführt
Nächste Schritte
- API-Zuordnung von In-Prozess zu isoliertem Worker – vollständige API-Referenz für die Migration
- Übersicht zu Durable Functions für .NET isolierten Worker
- Durable Functions Versions- und Migrationshandbuch
Verwandte Inhalte
- Official Microsoft Migrationsleitfaden (alle Azure Functions)
- .NET Übersicht über isolierte Workerprozesse
- Unterschiede beim isolierten Arbeitsmodell
- Serialisierung und Persistenz in Durable Functions
- Zero-Downtime-Bereitstellung für Durable Functions
- Konfigurieren eines dauerhaften Aufgabenplanungsmoduls