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.
In diesem Handbuch wird gezeigt, wie Sie Ihre Durable Functions Anwendung aus dem In-Process-Modell zum isolierten Workermodell migrieren.
Warnung
Die Unterstützung für das In-Process-Modell endet am 10. November 2026. Migrieren Sie zum isolierten Workermodell, um weiterhin Unterstützung und Zugriff auf neue Features zu erhalten.
Warum migrieren?
Ende des Supports für das Prozessmodell
Microsoft hat angekündigt, dass das In-Process-Modell für .NET Azure Functions am 10. November 2026 das Ende des Supports erreicht. Nach diesem Datum:
- Es werden keine Sicherheitsupdates bereitgestellt.
- Es werden keine Fehlerbehebungen veröffentlicht.
- Neue Features sind nur im isolierten Arbeitsmodell verfügbar.
Vorteile des isolierten Workermodells
Die Migration zum isolierten Arbeitsmodell bietet die folgenden Vorteile:
| Nutzen | Beschreibung |
|---|---|
| Keine Assemblykonflikte | Ihr Code wird in einem separaten Prozess ausgeführt, wodurch Versionskonflikte beseitigt werden. |
| Vollständige Prozesskontrolle | Steuern des Starts, der Konfiguration und der Middleware über Program.cs |
| Standard-DI-Muster | Vertraute .NET Abhängigkeitsinjektion verwenden |
| .NET-Versionsflexibilität | Unterstützung für LTS, STS und .NET Framework |
| Middleware-Unterstützung | Vollständige ASP.NET Core Middlewarepipeline |
| Bessere Leistung | ASP.NET Core Integration für HTTP-Trigger |
| Plattformunterstützung | Zugriff auf Flex-Verbrauchsplan und .NET Aspire |
Voraussetzungen
Bevor Sie die Migration starten, stellen Sie sicher, dass Sie über die folgenden Voraussetzungen verfügen:
- 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
- Vertrautheit mit Durable Functions Konzepten
Übersicht zur Migration
Der Migrationsprozess umfasst die folgenden Hauptschritte:
- Identifizieren der zu migrierenden Apps
- Aktualisieren der Projektdatei
- Hinzufügen von Program.cs
- Aktualisieren von Paketverweise
- Funktionscode aktualisieren
- Aktualisieren von local.settings.json
- Lokal testen
- Deploy to Azure
Identifizieren der zu migrierenden Apps
Verwenden Sie dieses Azure PowerShell Skript, um Funktions-Apps in Ihrem Abonnement zu finden, die das In-Process-Modell verwenden:
$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 verwenden, nutzen bereits das isolierte Workermodell.
Aktualisieren der Projektdatei
Vorher (im Prozess)
<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 Arbeiter)
<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
- Hinzufügen
<OutputType>Exe</OutputType>– Der isolierte Worker ist eine ausführbare Datei. - Hinzufügen von
<FrameworkReference Include="Microsoft.AspNetCore.App" />– Für ASP.NET Core Integration - Ersetzen Sie
Microsoft.NET.Sdk.FunctionsdurchMicrosoft.Azure.Functions.Worker.*Pakete - Ersetzen Sie
Microsoft.Azure.WebJobs.Extensions.DurableTaskdurchMicrosoft.Azure.Functions.Worker.Extensions.DurableTask
Hinzufügen von Program.cs
Erstellen Sie eine neue Program.cs Datei im Projektstamm:
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices(services => {
services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();
})
.Build();
host.Run();
Mit benutzerdefinierten Diensten
Wenn Sie eine FunctionsStartup Klasse hatten, verschieben Sie diese Konfiguration in Program.cs:
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices(services => {
// Application Insights
services.AddApplicationInsightsTelemetryWorkerService();
services.ConfigureFunctionsApplicationInsights();
// Your custom services (previously in FunctionsStartup)
services.AddSingleton<IMyService, MyService>();
services.AddHttpClient<IApiClient, ApiClient>();
})
.Build();
host.Run();
FunctionsStartup löschen
Wenn Sie ein Startup.cs mit [assembly: FunctionsStartup(...)] haben, löschen Sie es, nachdem Sie die Konfiguration in Program.cs verschoben haben.
Aktualisieren von Paketverweise
Durable Functions Paket-Änderungen
| In-Process-Paket | Isoliertes Arbeitspaket |
|---|---|
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 |
Allgemeine Änderungen des Erweiterungspakets
| 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
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;
}
After (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 |
Erneutes Wiederholen von Richtlinienänderungen
Bei der Verarbeitung werden RetryOptions mit CallActivityWithRetryAsync verwendet. Der isolierte Worker verwendet TaskOptions mit dem Standard CallActivityAsync.
Vorher (in Bearbeitung):
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 Bearbeitung):
[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;
}
}
After (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;
}
Vollständige API-Referenz
Die folgenden Tabellen enthalten eine umfassende Zuordnung zwischen dem In-Process 2.x SDK und den isolierten Worker-SDK-APIs.
Client-APIs
| Prozessintern (Version 2.x) | Eingeschlossener Mitarbeiter |
|---|---|
IDurableOrchestrationClient |
DurableTaskClient |
IDurableOrchestrationClient.StartNewAsync |
DurableTaskClient.ScheduleNewOrchestrationInstanceAsync |
IDurableOrchestrationClient.GetStatusAsync |
DurableTaskClient.GetInstanceAsync |
IDurableOrchestrationClient.ListInstancesAsync |
DurableTaskClient.GetAllInstancesAsync |
IDurableOrchestrationClient.TerminateAsync |
DurableTaskClient.TerminateInstanceAsync |
IDurableOrchestrationClient.SuspendAsync |
DurableTaskClient.SuspendInstanceAsync |
IDurableOrchestrationClient.ResumeAsync |
DurableTaskClient.ResumeInstanceAsync |
IDurableOrchestrationClient.RaiseEventAsync |
DurableTaskClient.RaiseEventAsync |
IDurableOrchestrationClient.RewindAsync |
DurableTaskClient.RewindInstanceAsync |
IDurableOrchestrationClient.RestartAsync |
DurableTaskClient.RestartAsync |
IDurableOrchestrationClient.PurgeInstanceHistoryAsync |
DurableTaskClient.PurgeInstanceAsync oder PurgeAllInstancesAsync |
IDurableOrchestrationClient.CreateCheckStatusResponse |
DurableTaskClient.CreateCheckStatusResponseAsync (Erweiterungsmethode, nimmt HttpRequestData) |
IDurableOrchestrationClient.WaitForCompletionOrCreateCheckStatusResponseAsync |
DurableTaskClient.WaitForCompletionOrCreateCheckStatusResponseAsync (Erweiterungsmethode, timeout ersetzt durch CancellationToken) |
IDurableOrchestrationClient.CreateHttpManagementPayload |
DurableTaskClient.CreateHttpManagementPayload (Erweiterungsmethode) |
IDurableOrchestrationClient.MakeCurrentAppPrimaryAsync |
Entfernt |
IDurableOrchestrationClient.GetStatusAsync(IEnumerable<string>) |
Entfernt Verwenden Sie GetInstanceAsync in einer Schleife oder GetAllInstancesAsync mit einem Abfragefilter. |
IDurableOrchestrationClient.PurgeInstanceHistoryAsync(IEnumerable<string>) |
Entfernt Benutzen Sie PurgeInstanceAsync in einer Schleife oder PurgeAllInstancesAsync mit einem Filter. |
IDurableOrchestrationClient.RaiseEventAsync (Überlastung des Cross-Task-Hubs mit taskHubName) |
Entfernt Nur das Auslösen von Ereignissen im gleichen Aufgabenhub wird unterstützt. |
IDurableEntityClient.SignalEntityAsync |
DurableTaskClient.Entities.SignalEntityAsync |
IDurableEntityClient.SignalEntityAsync (Überlastung des Cross-Task-Hubs mit taskHubName, connectionName) |
Entfernt Es werden nur Vorgänge von Entitäten im gleichen Aufgabenhub unterstützt. |
IDurableEntityClient.ReadEntityStateAsync |
DurableTaskClient.Entities.GetEntityAsync |
IDurableEntityClient.ReadEntityStateAsync (Cross-Task-Hub-Überlastung mit taskHubName, connectionName) |
Entfernt Es werden nur Vorgänge von Entitäten im gleichen Aufgabenhub unterstützt. |
IDurableEntityClient.ListEntitiesAsync |
DurableTaskClient.Entities.GetAllEntitiesAsync |
IDurableEntityClient.CleanEntityStorageAsync |
DurableTaskClient.Entities.CleanEntityStorageAsync (verwendet CleanEntityStorageRequest Objekt anstelle von Bool-Parametern) |
DurableOrchestrationStatus |
OrchestrationMetadata |
DurableOrchestrationStatus.History |
Aus statusobjekt entfernt. Verwenden Sie stattdessen DurableTaskClient.GetOrchestrationHistoryAsync. |
PurgeHistoryResult |
PurgeResult |
OrchestrationStatusQueryCondition |
OrchestrationQuery |
OrchestrationStatusQueryResult |
AsyncPageable<OrchestrationMetadata> |
Orchestrierungskontext-APIs
| Prozessintern (Version 2.x) | Eingeschlossener Mitarbeiter |
|---|---|
IDurableOrchestrationContext |
TaskOrchestrationContext |
IDurableOrchestrationContext.GetInput<T>() |
TaskOrchestrationContext.GetInput<T>() oder Einfügen von Eingaben als Parameter: MyOrchestration([OrchestrationTrigger] TaskOrchestrationContext context, T input) |
IDurableOrchestrationContext.SetOutput |
Entfernt Verwenden Sie den Rückgabewert aus der Orchestratorfunktion. |
IDurableOrchestrationContext.CallActivityWithRetryAsync |
TaskOrchestrationContext.CallActivityAsync mit einem TaskOptions Parameter für Wiederholungsdetails. |
IDurableOrchestrationContext.CallSubOrchestratorWithRetryAsync |
TaskOrchestrationContext.CallSubOrchestratorAsync mit einem Parameter TaskOptions für Wiederholungsdetails. |
IDurableOrchestrationContext.CallHttpAsync |
TaskOrchestrationContext.CallHttpAsync |
IDurableOrchestrationContext.CreateTimer<T>(DateTime, T, CancellationToken) |
TaskOrchestrationContext.CreateTimer(DateTime, CancellationToken). Zustandsparameter entfernt. |
IDurableOrchestrationContext.WaitForExternalEvent(string) (nicht generisch) |
Entfernt Verwenden Sie WaitForExternalEvent<T>(string, CancellationToken). |
IDurableOrchestrationContext.WaitForExternalEvent<T>(string, TimeSpan, T) (mit defaultValue) |
Entfernt Verwenden Sie WaitForExternalEvent<T>(string, TimeSpan, CancellationToken), die bei einem Timeout TaskCanceledException auslöst. |
IDurableOrchestrationContext.ParentInstanceId |
TaskOrchestrationContext.Parent.InstanceId |
IDurableOrchestrationContext.CreateReplaySafeLogger(ILogger) |
TaskOrchestrationContext.CreateReplaySafeLogger<T>() oder TaskOrchestrationContext.CreateReplaySafeLogger(string) |
IDurableOrchestrationContext.CreateEntityProxy<T> |
Entfernt Verwenden Sie Entities.CallEntityAsync oder Entities.SignalEntityAsync direkt. |
IDurableOrchestrationContext.CallEntityAsync |
TaskOrchestrationContext.Entities.CallEntityAsync |
IDurableOrchestrationContext.SignalEntity |
TaskOrchestrationContext.Entities.SignalEntityAsync |
IDurableOrchestrationContext.LockAsync |
TaskOrchestrationContext.Entities.LockEntitiesAsync |
IDurableOrchestrationContext.IsLocked |
TaskOrchestrationContext.Entities.InCriticalSection() |
RetryOptions |
TaskOptions mit TaskRetryOptions |
DurableActivityContext |
Keine Entsprechung |
DurableActivityContext.GetInput<T>() |
Einfügen von Eingaben als Parameter: MyActivity([ActivityTrigger] T input) |
DurableHttpRequest (WebJobs-Namespace) |
DurableHttpRequest (Microsoft.Azure.Functions.Worker.Extensions.DurableTask.Http-Namespace) |
DurableHttpResponse (WebJobs-Namespace) |
DurableHttpResponse (Microsoft.Azure.Functions.Worker.Extensions.DurableTask.Http-Namespace) |
Entitäts-APIs
| Prozessintern (Version 2.x) | Eingeschlossener Mitarbeiter |
|---|---|
IDurableEntityContext |
TaskEntityContext |
IDurableEntityContext.EntityName |
TaskEntityContext.Id.Name |
IDurableEntityContext.EntityKey |
TaskEntityContext.Id.Key |
IDurableEntityContext.OperationName |
TaskEntityOperation.Name |
IDurableEntityContext.FunctionBindingContext |
Entfernt Als Eingabeparameter hinzufügen FunctionContext . |
IDurableEntityContext.HasState |
TaskEntityOperation.State.HasState |
IDurableEntityContext.GetState |
TaskEntityOperation.State.GetState |
IDurableEntityContext.SetState |
TaskEntityOperation.State.SetState |
IDurableEntityContext.DeleteState |
TaskEntityOperation.State.SetState(null) |
IDurableEntityContext.GetInput |
TaskEntityOperation.GetInput |
IDurableEntityContext.Return |
Entfernt Verwenden Sie stattdessen den Rückgabewert der Methode. |
IDurableEntityContext.SignalEntity |
TaskEntityContext.SignalEntity. Geplante Signale verwenden SignalEntityOptions.SignalTime anstelle einer Parameterüberladung DateTime. |
IDurableEntityContext.StartNewOrchestration |
TaskEntityContext.ScheduleNewOrchestration. Die Instanz-ID wird über StartOrchestrationOptions.InstanceId und nicht über einen Zeichenfolgenparameter festgelegt. |
IDurableEntityContext.DispatchAsync |
TaskEntityDispatcher.DispatchAsync. Konstruktorparameter entfernt; Verwenden Sie stattdessen Standard-DI. |
IDurableEntityContext.BatchSize |
Entfernt |
IDurableEntityContext.BatchPosition |
Entfernt |
Änderungen des Verhaltens
-
Serialisierung: Der Standard-Serialisierer wurde von
Newtonsoft.JsonzuSystem.Text.Json. Weitere Informationen finden Sie unter Serialisierung und Persistenz in Durable Functions.
Warnung
ContinueAsNew Standardänderung: Der Standardwert des preserveUnprocessedEvents-Parameters wurde von false (2.x) auf true (isolated) geändert. Wenn Ihre Orchestrierung ContinueAsNew verwendet und sich darauf stützt, dass unverarbeitete Ereignisse verworfen werden, übergeben Sie preserveUnprocessedEvents: false explizit.
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.
-
Entfernung des Entitätsproxys:
CreateEntityProxy<T>Und die typiertenSignalEntityAsync<TEntityInterface>(Action<T>)Delegatüberladungen sind im isolierten Worker nicht verfügbar. Rufen SieEntities.CallEntityAsyncoderEntities.SignalEntityAsyncdirekt mit Zeichenfolgenbasierten Vorgangsnamen auf, anstatt eingegebene Proxyschnittstellen zu verwenden. -
WaitForCompletionOrCreateCheckStatusResponseAsync: Der
timeoutParameter wurde entfernt. Verwenden Sie stattdessen ein Abbruch-Timeout mitCancellationToken. -
Aufgabenübergreifende Vorgänge wurden entfernt: Die In-Process-Überladungen, die die
taskHubNameundconnectionNameParameter akzeptierten (beiRaiseEventAsync,SignalEntityAsyncundReadEntityStateAsync), sind in isolierten Workern nicht verfügbar. Es werden nur Vorgänge desselben Task-Hubs unterstützt. -
Batchvorgänge nach ID entfernt: Die im Prozess
GetStatusAsync(IEnumerable<string>)- undPurgeInstanceHistoryAsync(IEnumerable<string>)-Überladungsfunktionen sind in isolierten Arbeitern nicht verfügbar. Verwenden SieGetAllInstancesAsyncmit einemOrchestrationQuery-Filter oder rufen SieGetInstanceAsync/PurgeInstanceAsynceinzeln auf.PurgeInstanceAsync -
Der Orchestrierungsverlauf wurde verschoben:
DurableOrchestrationStatus.History(eingebettetJArray) ist nicht mehr Teil des Statusobjekts. Verwenden Sie die separateDurableTaskClient.GetOrchestrationHistoryAsyncAPI zum Abrufen des Orchestrierungsverlaufs. -
Entity DispatchAsync-Konstruktorparameter entfernt: Die
DispatchAsync<T>(params object[])Konstruktorparameterüberladung ist nicht verfügbar. Entitätsklassen werden über die Standardmäßige Abhängigkeitsinjektion aktiviert. Registrieren Sie die Abhängigkeiten Ihrer Entität inProgram.cs. - Änderungen des Entitätsabfragefilters:
EntityQuery.EntityNamewird durchEntityQuery.InstanceIdStartsWithersetzt undEntityQuery.IncludeDeletedwird durchEntityQuery.IncludeTransientersetzt. -
CleanEntityStorageAsync-Signaturänderung: Anstelle der
(bool removeEmptyEntities, bool releaseOrphanedLocks, CancellationToken)isolierten Version wird einCleanEntityStorageRequestObjekt mitRemoveEmptyEntitiesundReleaseOrphanedLocksEigenschaften verwendet. -
Neue APIs im isolierten Worker:
DurableTaskClient.GetOrchestrationHistoryAsyncUnd dieTaskOrchestrationContext.GetFunctionContext()Erweiterungsmethode ist im isolierten Worker verfügbar, hat jedoch keine In-Process-Entsprechung.
Aktualisieren von local.settings.json
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated",
"DURABLE_TASK_SCHEDULER_CONNECTION_STRING": "Endpoint=http://localhost:8080;Authentication=None"
}
}
Die Schlüsseländerung erfolgt FUNCTIONS_WORKER_RUNTIME von dotnet zu dotnet-isolated.
Lokal testen
Starten des Emulators
docker run -d -p 8080:8080 -p 8082:8082 mcr.microsoft.com/dts/dts-emulator:latest
Führen Sie die Funktions-App aus
func start
Überprüfen der Funktionalität
Testen Sie alle Ihre Orchestrierungen, Aktivitäten und Entitäten, um sicherzustellen, dass sie ordnungsgemäß funktionieren:
- 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
Bereitstellen auf Azure
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 Staging-Slot.
- 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.
Solution: 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 IMessageSerializerSettingsFactory im In-Process-Modell die JSON-Serialisierung für Orchestrierungseingaben, Ausgaben oder den Entitätsstatus angepasst und benötigen das Äquivalent in einem isolierten Worker.
Lösung: Die IMessageSerializerSettingsFactory Schnittstelle ist in isolierten Workern nicht verfügbar. Konfigurieren Sie stattdessen den Serialisierer auf Arbeitsebene in Program.cs:
Vor (in Bearbeitung)
// Startup.cs
[assembly: FunctionsStartup(typeof(MyStartup))]
public class MyStartup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddSingleton<IMessageSerializerSettingsFactory, CustomSerializerSettingsFactory>();
}
}
Nach (Isolierter Arbeiter):
// 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. Die Einstellung WorkerOptions.Serializer gilt global für alles, was von der erweiterung Durable Functions serialisiert wird. Weitere Informationen finden Sie unter Serialisierung und Persistenz in Durable Functions.
Checklist
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 - Mit Hostkonfiguration erstellt
Program.cs - Klasse
FunctionsStartupentfernt (sofern vorhanden) - Alle
[FunctionName]aktualisiert auf[Function] - Ersetzt
IDurableOrchestrationContextdurchTaskOrchestrationContext - Ersetzt
IDurableOrchestrationClientdurchDurableTaskClient - Aktualisierte Protokollierung für die Verwendung von DI oder
FunctionContext - Aktualisiert
local.settings.jsonmitdotnet-isolatedLaufzeit - Alle
Microsoft.Azure.WebJobs.*using-Anweisungen entfernt - Using-Anweisungen
Microsoft.Azure.Functions.Workerhinzugefügt - Ersetzt
CreateEntityProxy<T>durch direkteCallEntityAsync/SignalEntityAsyncAnrufe - Ersetzte Cross-Task-Hub-Betriebsüberladungen (falls verwendet)
- Batch-
GetStatusAsync/PurgeInstanceHistoryAsyncby-ID Anrufe durch filterbasierte oder einzelne Anrufe ersetzt - Migrierter
DurableOrchestrationStatus.HistoryZugriff aufGetOrchestrationHistoryAsync - Aktualisierte Entitätskonstruktorparameter
DispatchAsyncfür die Verwendung von DI - Lokales Testen aller Funktionen
- Bereitgestellt für Staging-Steckplatz und überprüft
- In die Produktion überführt
Nächste Schritte
- Übersicht über .NET isolierten Arbeitsprozess
- Übersicht zu Durable Functions für .NET isolierten Worker
- Durable Functions Muster und technische Konzepte
Weitere Ressourcen
- Offizieller Microsoft-Migrationsleitfaden
- Unterschiede beim isolierten Arbeitsmodell
- Handbuch für Unit-Tests von Durable Functions (isoliert)
- Serialisierung und Persistenz in Durable Functions
- Versionierung in dauerhaften Funktionen
- Zero-Downtime-Bereitstellung für Durable Functions
- Konfigurieren eines dauerhaften Aufgabenplanungsmoduls
- Code-Beispiele für Durable Functions