Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Tato příručka vás provede migrací aplikace .NET Durable Functions z modelu v procesu na izolovaný pracovní model. Model v procesu dosáhne konce podpory 10. listopadu 2026. Po tomto datu nejsou k dispozici žádné aktualizace zabezpečení ani opravy chyb. Model izolovaného pracovního procesu také poskytuje úplné řízení procesů, standardní .NET injektáž závislostí a přístup k nejnovějším funkcím platformy.
Important
Support pro model v procesu skončí 10. listopadu 2026. Důrazně doporučujeme migrovat aplikace do izolovaného modelu pracovních procesů pro plnou podporu.
Kontrolní seznam pro migraci
Pomocí následujícího kontrolního seznamu můžete sledovat průběh jednotlivých kroků migrace:
| Krok | Oddíl |
|---|---|
| 1. Ověření požadavků | Prerequisites |
| 2. Aktualizace souboru projektu | Aktualizace souboru projektu |
| 3. Přidejte Program.cs | Přidat Program.cs |
| 4. Aktualizace odkazů na balíčky | Aktualizace odkazů na balíčky |
| 5. Aktualizace kódu funkce | Aktualizace kódu funkce |
| 6. Aktualizace local.settings.json | Aktualizace local.settings.json |
| 7. Místní testování | Místní testování |
| 8. Nasazení do Azure | Nasazení do Azure |
Předpoklady
- Azure Functions Core Tools verze 4.x nebo novější
- .NET 8.0 SDK (nebo cílovou .NET verzi)
- Visual Studio 2022 nebo VS Code with Azure Functions extension
Identifikace aplikací, které se mají migrovat (volitelné)
Pokud si nejste jistí, které aplikace stále používají model v procesu, spusťte tento Azure PowerShell skript:
$FunctionApps = Get-AzFunctionApp
$AppInfo = @{}
foreach ($App in $FunctionApps)
{
if ($App.Runtime -eq 'dotnet')
{
$AppInfo.Add($App.Name, $App.Runtime)
}
}
$AppInfo
Aplikace, které zobrazují dotnet jako runtime, používají model v paměti procesu. Aplikace, které už zobrazují dotnet-isolated , používají izolovaný model pracovního procesu.
Aktualizace souboru projektu
Předchozí (během zpracování)
<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>
Po izolovaném pracovníkovi
<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>
Hlavní změny zahrnují přechod na typ výstupu spustitelného souboru a nahrazení všech balíčků Microsoft.Azure.WebJobs.* jejich ekvivalenty Microsoft.Azure.Functions.Worker.*.
Přidejte Program.cs
Izolovaný model pracovního procesu vyžaduje Program.cs vstupní bod. Vytvořte tento soubor v kořenovém adresáři projektu. Pokud máte třídu FunctionsStartup v Startup.cs, přesuňte tyto registrace služeb do bloku ConfigureServices a odstraňte 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();
Aktualizace odkazů na balíčky
mapování balíčků Durable Functions
| Balíček v procesu | Izolovaný pracovní balíček |
|---|---|
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 |
Běžné mapování balíčků rozšíření
| Zpracovává se | Izolovaný pracovník |
|---|---|
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
Odeberte všechny odkazy na obory názvů Microsoft.Azure.WebJobs.* a Microsoft.Azure.Functions.Extensions z projektu.
Aktualizace kódu funkce
Tato část popisuje změny kódu pro každý typ Durable Functions. Přejděte do části pro typy funkcí, které vaše aplikace používá:
- Změny jmenného prostoru
- Funkce orchestratoru
- Funkce aktivit
- Klientské funkce
- Zásady opakování (pokud se používají)
- Funkce entity (pokud se používají)
Kompletní mapování rozhraní API podle rozhraní API najdete v referenčních informacích k rozhraní API.
Změny jmenného prostoru
// 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;
Změny atributů funkce
// Before (In-Process)
[FunctionName("MyOrchestrator")]
// After (Isolated Worker)
[Function(nameof(MyOrchestrator))]
Změny funkce orchestratoru
Před (Ve zpracování):
[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 };
}
Za (izolovaný pracovník):
[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 };
}
Hlavní rozdíly
| Aspect | V procesu | Izolovaný pracovník |
|---|---|---|
| Typ kontextu | IDurableOrchestrationContext |
TaskOrchestrationContext |
| Logger |
ILogger Parametr |
context.CreateReplaySafeLogger() |
| Atribut | [FunctionName] |
[Function] |
Změny funkce aktivity
Před (Ve zpracování):
[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;
}
Za (izolovaný pracovník):
[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;
}
Změny funkce klienta
Před (Ve zpracování):
[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);
}
Za (izolovaný pracovník):
[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);
}
Změny typu klienta
| Zpracovává se | Izolovaný pracovník |
|---|---|
IDurableOrchestrationClient |
DurableTaskClient |
StartNewAsync() |
ScheduleNewOrchestrationInstanceAsync() |
CreateCheckStatusResponse() |
CreateCheckStatusResponseAsync() |
HttpRequest / IActionResult |
HttpRequestData / HttpResponseData |
Změny zásad opakování
In-process používá RetryOptions s CallActivityWithRetryAsync. Izolovaný pracovník používá TaskOptions se standardním CallActivityAsync.
Před (Ve zpracování):
var retryOptions = new RetryOptions(
firstRetryInterval: TimeSpan.FromSeconds(5),
maxNumberOfAttempts: 3);
string result = await context.CallActivityWithRetryAsync<string>(
"MyActivity", retryOptions, input);
Za (izolovaný pracovník):
var retryOptions = new TaskOptions(
new TaskRetryOptions(new RetryPolicy(
maxNumberOfAttempts: 3,
firstRetryInterval: TimeSpan.FromSeconds(5))));
string result = await context.CallActivityAsync<string>(
"MyActivity", input, retryOptions);
Změny funkce entity
Před (Ve zpracování):
[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;
}
}
Za (izolovaný pracovník):
[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;
}
Zásadní změny chování
Před otestem migrované aplikace si tyto změny projděte. Kompletní mapování rozhraní API podle rozhraní API najdete v referenčních informacích k rozhraní API.
Warning
Změna výchozího nastavení serializace: Izolovaný pracovní proces používá System.Text.Json ve výchozím nastavení místo Newtonsoft.Json. Pokud vaše orchestrace předávají složité objekty, důkladně otestujte serializaci. Možnosti konfigurace najdete v rozdílech serializace JSON .
Warning
ContinueAsNew default change: Výchozí hodnota parametru preserveUnprocessedEvents byla změněna z false (2.x) na true (isolated). Pokud orchestrace používá ContinueAsNew a spoléhá na to, že nezpracované události mají být zahozeny, explicitně předejte preserveUnprocessedEvents: false.
Note
Výchozí změna restartAsync: Výchozí restartWithNewInstanceId parametr se změnil z true (2.x) na false (izolovaný). Pokud váš kód volá RestartAsync a závisí na vygenerovaném novém ID instance, explicitně předejte restartWithNewInstanceId: true.
Další velmi vhodné změny:
-
Proxy entity byly odebrány –
CreateEntityProxy<T>není k dispozici. PoužijteEntities.CallEntityAsyncneboEntities.SignalEntityAsyncpřímo. -
Operace mezi úlohami rozbočovače byly odebrány – přetížení, která přijímala
taskHubName/connectionName, nejsou k dispozici. Podporují se pouze operace stejného centra úloh. -
Historie orchestrace byla přesunuta –
DurableOrchestrationStatus.Historyuž není na objektu stavu. PoužijteDurableTaskClient.GetOrchestrationHistoryAsync.
Aktualizace local.settings.json
Zásadní změnou je nastavení FUNCTIONS_WORKER_RUNTIME z dotnet na dotnet-isolated.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
}
}
Note
Migrace nemění konfiguraci back-endu úložiště (Azure Storage, MSSQL, Netherite nebo Durable Task Scheduler). Ponechte stávající nastavení související s úložištěm.
Místní testování
Spusťte aplikaci funkcí místně a ověřte, že všechny orchestrace, aktivity a entity fungují správně.
func start
Ověření funkčnosti
Podle potřeby otestujte následující scénáře:
- Spuštění orchestrace pomocí triggeru HTTP
- Monitorování stavu orchestrace
- Ověření pořadí provádění aktivit
- Otestujte operace entit, pokud je to vhodné
- Zkontrolovat telemetrii Application Insights
Nasazení do Azure
Doporučeno: Používejte sloty nasazení
K minimalizaci výpadků použijte sloty nasazení:
- Vytvořte přípravný slot pro vaši funkční aplikaci.
-
Aktualizace konfigurace staging slotu:
- Nastavte
FUNCTIONS_WORKER_RUNTIMEna hodnotudotnet-isolated. - V případě potřeby aktualizujte verzi .NET zásobníku.
- Nastavte
- Nasaďte migrovaný kód do přípravného slotu.
- Důkladně otestujte v testovací fázi.
- Proveďte prohození slotů a přesuňte změny do produkčního prostředí.
Aktualizace nastavení aplikace
Na portálu Azure nebo prostřednictvím rozhraní příkazového řádku:
az functionapp config appsettings set \
--name <FUNCTION_APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--settings FUNCTIONS_WORKER_RUNTIME=dotnet-isolated
Aktualizace konfigurace stacku
Pokud cílíte na jinou verzi .NET:
az functionapp config set \
--name <FUNCTION_APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--net-framework-version v8.0
Běžné problémy s migrací
Problém: Chyby načtení sestavení
Příznaky:Could not load file or assembly Chyby.
Solution: Ujistěte se, že odeberete všechny odkazy na balíčky Microsoft.Azure.WebJobs.* a nahradíte je izolovanými pracovními ekvivalenty.
Problém: Atribut vazby nebyl nalezen.
Příznak:The type or namespace 'QueueTrigger' could not be found
Řešení: Přidejte příslušný balíček rozšíření a aktualizujte příkazy using:
// Add using statement
using Microsoft.Azure.Functions.Worker;
// Install package
// dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues
Problém: IDurableOrchestrationContext se nenašel
Příznak:The type or namespace 'IDurableOrchestrationContext' could not be found
Řešení: Nahradit:TaskOrchestrationContext
using Microsoft.DurableTask;
[Function(nameof(MyOrchestrator))]
public static async Task MyOrchestrator([OrchestrationTrigger] TaskOrchestrationContext context)
{
// ...
}
Problém: Rozdíly serializace JSON
Příznakem: Chyby serializace nebo neočekávané formáty dat
Řešení: Izolovaný model používá System.Text.Json ve výchozím nastavení. Konfigurace serializace v Program.cs:
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices(services => {
services.Configure<JsonSerializerOptions>(options => {
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
})
.Build();
Pokud chcete místo toho použít Newtonsoft.Json:
services.Configure<WorkerOptions>(options => {
options.Serializer = new NewtonsoftJsonObjectSerializer();
});
Problém: Migrace vlastního nastavení serializace
Příznak: Použili jste IMessageSerializerSettingsFactory v modelu v rámci procesu a potřebujete ekvivalent v izolovaném workeru.
Řešení: Nakonfigurujte serializátor na úrovni pracovníka v Program.cs. Pro podrobnosti se podívejte na část změny chování referenční dokumentace k rozhraní API a Serializace a perzistence v Durable Functions.
K použití Newtonsoft.Json s vlastním nastavením:
// 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
Tento přístup vyžaduje balíčky NuGet Newtonsoft.Json a Azure.Core.Serialization.
Kontrolní seznam
K zajištění úplné migrace použijte tento kontrolní seznam:
- Aktualizovaný soubor projektu pomocí
<OutputType>Exe</OutputType> - Nahrazeno
Microsoft.NET.Sdk.Functionspracovními balíčky - Nahrazeno
Microsoft.Azure.WebJobs.Extensions.DurableTaskizolovaným balíčkem - Vytvořeno
Program.css konfigurací hostitelského systému -
FunctionsStartupOdebrání třídy (pokud je k dispozici) - Aktualizováno vše
[FunctionName]na[Function] - Nahrazeno
IDurableOrchestrationContextzaTaskOrchestrationContext - Nahrazeno
IDurableOrchestrationClientzaDurableTaskClient - Aktualizované protokolování tak, aby používalo DI nebo
FunctionContext - Aktualizováno
local.settings.jsonmodulemdotnet-isolatedruntime - Odebrali se všechny příkazy
Microsoft.Azure.WebJobs.*using - Přidání příkazů
Microsoft.Azure.Functions.Workerusing - Nahrazeno
CreateEntityProxy<T>přímýmiCallEntityAsync/SignalEntityAsyncvoláními - Nahrazení přetížení operací mezi uzly úloh (pokud se používá)
- Dávkové volání
GetStatusAsync/PurgeInstanceHistoryAsyncpodle ID bylo nahrazeno voláními na základě filtru nebo jednotlivými voláními. - Migrovaný
DurableOrchestrationStatus.Historypřístup kGetOrchestrationHistoryAsync - Aktualizace parametrů konstruktoru entity
DispatchAsynctak, aby používaly DI - Místní otestování všech funkcí
- Nasazené do přípravného slotu a ověřené
- Prohozeno do produkčního prostředí
Další kroky
- Mapování izolovaného pracovního rozhraní API v procesu – kompletní referenční informace k rozhraní API pro vaši migraci
- Přehled Durable Functions pro izolovaný pracovní proces v .NET
- Verze Durable Functions a průvodce migrací