Az Ön Durable Functions alkalmazásának migrálása az in-process modellről az izolált munkavállalói modellre (.NET)

Ez az útmutató végigvezeti a .NET Durable Functions alkalmazás migrálásán a folyamatban lévő modellről az izolált feldolgozói modellre. A folyamatban lévő modell 2026. november 10-én véget ér a támogatásnak. Ezt követően a rendszer nem biztosít biztonsági frissítéseket vagy hibajavításokat. Az izolált feldolgozói modell teljes folyamatvezérlést, standard .NET függőséginjektálást és hozzáférést biztosít a legújabb platformfunkciókhoz.

Warning

A folyamatban lévő modell támogatása 2026. november 10-én megszűnik. Javasoljuk a migrálást. Az izolált feldolgozói modell hátteréről lásd: .NET izolált feldolgozói folyamat áttekintése.

Migrálási ellenőrzőlista

Az alábbi ellenőrzőlistával nyomon követheti az egyes migrálási lépések előrehaladását:

Lépés Szakasz
1. Az előfeltételek ellenőrzése Prerequisites
2. A projektfájl frissítése A projektfájl frissítése
3. Program.cs hozzáadása Program.cs hozzáadása
4. Csomaghivatkozások frissítése Csomaghivatkozások frissítése
5. Függvénykód frissítése Függvénykód frissítése
6. local.settings.json frissítése local.settings.jsonfrissítése
7. Helyi tesztelés Helyi tesztelés
8. Üzembe helyezés az Azure-ba Üzembe helyezés az Azure-ban

Prerequisites

  • Azure Functions Core Tools v4.x vagy újabb
  • .NET 8.0 SDK (vagy a cél .NET verziója)
  • Visual Studio 2022 vagy VS-kód Azure Functions kiterjesztéssel

A migrálni kívánt alkalmazások azonosítása (nem kötelező)

Ha nem biztos abban, hogy mely alkalmazások használják továbbra is a folyamatban lévő modellt, futtassa ezt a Azure PowerShell szkriptet:

$FunctionApps = Get-AzFunctionApp

$AppInfo = @{}

foreach ($App in $FunctionApps)
{
     if ($App.Runtime -eq 'dotnet')
     {
          $AppInfo.Add($App.Name, $App.Runtime)
     }
}

$AppInfo

A futtatókörnyezetként megjelenített dotnet alkalmazások a folyamatban lévő modellt használják. Azok az alkalmazások, amelyek dotnet-isolated megjelenítik, már használják az izolált feldolgozói modellt.

A projektfájl frissítése

Előtte (folyamatban)

<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>

After (izolált munkaegység)

<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>

A fő változások a végrehajtható kimeneti típusra való váltás, és az összes Microsoft.Azure.WebJobs.* csomag lecserélése a Microsoft.Azure.Functions.Worker.*-ekvivalensekre.

Program.cs hozzáadása

Az izolált dolgozói modellhez belépési pont szükséges Program.cs. Hozza létre ezt a fájlt a projekt gyökérkönyvtárában. Ha van egy FunctionsStartup osztálya a Startup.cs-ban/-ben, helyezze át ezeket a szolgáltatásregisztrációkat a ConfigureServices blokkba, és törölje a Startup.cs elemet.

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();

Csomaghivatkozások frissítése

Durable Functions csomagleképezés

Folyamatban lévő csomag Izolált munkavállalói csomag
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

A bővítménycsomagok gyakori hozzárendelése

Folyamatban Izolált munkavégző
Microsoft.Azure.WebJobs.Extensions.Storage \, \, \
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

Távolítsa el a Microsoft.Azure.WebJobs.* névterekre és Microsoft.Azure.Functions.Extensions mutató hivatkozásokat a projektből.

Függvénykód frissítése

Ez a szakasz az egyes Durable Functions-típusok kódmódosítását ismerteti. Ugorjon az alkalmazás által használt függvénytípusok szakaszára:

Az API-nkénti teljes leképezésért tekintse meg az API-referenciát.

Névtérváltozások

// 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;

Függvényattribútum változásai

// Before (In-Process)
[FunctionName("MyOrchestrator")]

// After (Isolated Worker)
[Function(nameof(MyOrchestrator))]

Az Orchestrator függvények változásai

Előtte (Folyamatban):

[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 };
}

After (izolált munkafolyamat):

[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 };
}

Főbb különbségek

Szempont Folyamatban Izolált munkás
Környezet típusa IDurableOrchestrationContext TaskOrchestrationContext
Logger ILogger Paraméter context.CreateReplaySafeLogger()
Attribútum [FunctionName] [Function]

Tevékenységfüggvény változásai

Előtte (Folyamatban):

[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 (izolált munkafolyamat):

[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;
}

Ügyfélfunkció változásai

Előtte (Folyamatban):

[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);
}

After (izolált munkafolyamat):

[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);
}

Ügyféltípus-módosítások

Folyamatban Izolált munkavégző
IDurableOrchestrationClient DurableTaskClient
StartNewAsync() ScheduleNewOrchestrationInstanceAsync()
CreateCheckStatusResponse() CreateCheckStatusResponseAsync()
HttpRequest / IActionResult HttpRequestData / HttpResponseData

Szabályzatmódosítások újrapróbálkozása

A folyamatban használt RetryOptions a CallActivityWithRetryAsync-vel. Az izolált dolgozó a standard TaskOptions-t használjaCallActivityAsync.

Előtte (Folyamatban):

var retryOptions = new RetryOptions(
    firstRetryInterval: TimeSpan.FromSeconds(5),
    maxNumberOfAttempts: 3);

string result = await context.CallActivityWithRetryAsync<string>(
    "MyActivity", retryOptions, input);

After (izolált munkafolyamat):

var retryOptions = new TaskOptions(
    new TaskRetryOptions(new RetryPolicy(
        maxNumberOfAttempts: 3,
        firstRetryInterval: TimeSpan.FromSeconds(5))));

string result = await context.CallActivityAsync<string>(
    "MyActivity", input, retryOptions);

Entitásfunkció változások

Előtte (Folyamatban):

[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 (izolált munkafolyamat):

[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;
}

A kompatibilitástörő viselkedés változásai

A migrált alkalmazás tesztelése előtt tekintse át ezeket a módosításokat. Az API-nkénti teljes leképezéshez tekintse meg az API-referenciát.

Warning

A szerializálás alapértelmezése megváltozott: Az izolált feldolgozó alapértelmezés szerint most System.Text.Json-t használ Newtonsoft.Json helyett. Ha az orchestration-ök összetett objektumokat kezelnek, gondosan tesztelje a szerializálást. A konfigurációs beállítások JSON-szerializálási különbségeit lásd.

Warning

ContinueAsNew alapértelmezett változás: Az preserveUnprocessedEvents paraméter alapértelmezett értéke megváltozott false (2.x)-ről true (izolált)-ra. Ha az orchestráció ContinueAsNew és a feldolgozatlan események elvetésére támaszkodik, adja át explicit módon a preserveUnprocessedEvents: false.

Note

RestartAsync alapértelmezett módosítása: Az restartWithNewInstanceId paraméter alapértelmezése megváltozott a true (2.x) értékről false (izolált) értékre. Ha a kód meghívja RestartAsync, és függ attól, hogy új példányazonosító generálódjon, akkor explicit módon adja át restartWithNewInstanceId: true.

Egyéb jelentős változások:

  • Az entitás-proxyk el lettek távolítvaCreateEntityProxy<T> nem érhető el. Használja Entities.CallEntityAsync vagy Entities.SignalEntityAsync közvetlenül.
  • A feladatközpontok közötti műveletek el lettek távolítva – Az elfogadott taskHubName/connectionName túlterhelések nem érhetők el. Csak az azonos feladatközponti műveletek támogatottak.
  • Az orchestrációs előzmények áthelyezveDurableOrchestrationStatus.History már nem szerepel az állapot objektumban. Használja a DurableTaskClient.GetOrchestrationHistoryAsync.

local.settings.jsonfrissítése

A kulcs változtatása FUNCTIONS_WORKER_RUNTIME-ról dotnet-ra setting dotnet-isolated:

{
    "IsEncrypted": false,
    "Values": {
        "AzureWebJobsStorage": "UseDevelopmentStorage=true",
        "FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
    }
}

Note

A háttérrendszer konfigurációját (Azure Storage, MSSQL, Netherite vagy Durable Task Scheduler) az áttelepítés nem változtatja meg. Tartsa meg a meglévő tárolási beállításokat.

Helyi tesztelés

Futtassa helyileg a függvényalkalmazást, és ellenőrizze, hogy az összes vezénylés, tevékenység és entitás megfelelően működik-e.

func start

Funkciók ellenőrzése

Tesztelje a következő forgatókönyveket a megfelelő módon:

  1. Folyamatvezérlés indítása HTTP-eseményindítóval
  2. A vezénylés állapotának figyelése
  3. A tevékenység végrehajtási megrendelésének ellenőrzése
  4. Entitásműveletek tesztelése, ha vannak
  5. Az Application Insights telemetriájának ellenőrzése

Telepítés az Azure-ra

Üzembehelyezési pontok használata az állásidő minimalizálásához:

  1. Hozzon létre egy átmeneti pontot a függvényalkalmazáshoz.
  2. Az előkészítési pont konfigurációjának frissítése:
    • Állítsa be FUNCTIONS_WORKER_RUNTIME-t dotnet-isolated-re.
    • Szükség esetén frissítse .NET veremverziót.
  3. Telepítse a migrált kódot az előkészítési résbe.
  4. Tesztelje alaposan az előkészítési ponton.
  5. Slot cserét hajtson végre a változtatások éles környezetbe viteléhez.

Alkalmazásbeállítások frissítése

A Azure portálon vagy a parancssori felületen:

az functionapp config appsettings set \
    --name <FUNCTION_APP_NAME> \
    --resource-group <RESOURCE_GROUP> \
    --settings FUNCTIONS_WORKER_RUNTIME=dotnet-isolated

Veremkonfiguráció frissítése

Ha másik .NET verziót céloz meg:

az functionapp config set \
    --name <FUNCTION_APP_NAME> \
    --resource-group <RESOURCE_GROUP> \
    --net-framework-version v8.0

Gyakori migrációs problémák

Probléma: Szerelvénybetöltési hibák

Tünet:Could not load file or assembly hibák.

Solution: Győződjön meg arról, hogy az összes Microsoft.Azure.WebJobs.* csomaghivatkozást eltávolítja, és azokat izolált feldolgozó-megfelelőkre cseréli.

Probléma: A kötési attribútum nem található

Tünet:The type or namespace 'QueueTrigger' could not be found

Megoldás: Adja hozzá a megfelelő bővítménycsomagot, és frissítse a using utasításokat.

// Add using statement
using Microsoft.Azure.Functions.Worker;

// Install package
// dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues

Probléma: Az IDurableOrchestrationContext nem található

Tünet:The type or namespace 'IDurableOrchestrationContext' could not be found

Megoldás: Cserélje le a következőre TaskOrchestrationContext:

using Microsoft.DurableTask;

[Function(nameof(MyOrchestrator))]
public static async Task MyOrchestrator([OrchestrationTrigger] TaskOrchestrationContext context)
{
    // ...
}

Probléma: JSON szerializálási különbségek

Tünet: Szerializálási hibák vagy váratlan adatformátumok

Megoldás: Az izolált modell alapértelmezés szerint használ System.Text.Json . Szerializálás konfigurálása a következőben Program.cs:

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services => {
        services.Configure<JsonSerializerOptions>(options => {
            options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
        });
    })
    .Build();

A Newtonsoft.Json használatához:

services.Configure<WorkerOptions>(options => {
    options.Serializer = new NewtonsoftJsonObjectSerializer();
});

Probléma: Egyéni szerializálási beállítások áttelepítése

Tünet: A folyamaton belüli modellben használta a IMessageSerializerSettingsFactory , és az elszigetelt munkavállalóban az ennek megfelelőre van szüksége.

Megoldás: A feldolgozószintű szerializáló Program.cs konfigurálása. További részletekért tekintse meg a viselkedési változások szakaszát az API-referenciában és az Adatszerializálás és tartósság a Durable Functionsben.

A Newtonsoft.Json használata egyéni beállításokkal:

// 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

Ehhez a megközelítéshez Newtonsoft.Json és Azure.Core.Serialization NuGet-csomagokra van szükség.

Checklist

Ezzel az ellenőrzőlistát használva biztosíthatja a teljes migrálást:

  • Projektfájlt frissítettem a <OutputType>Exe</OutputType>
  • Microsoft.NET.Sdk.Functions helyett munkacsomagok
  • Microsoft.Azure.WebJobs.Extensions.DurableTask izolált csomagra cserélve
  • Gazdagépkonfigurációval létrehozva Program.cs
  • Eltávolított FunctionsStartup osztály (ha van)
  • Frissítettem az összes [FunctionName][Function]-re.
  • IDurableOrchestrationContext helyébe TaskOrchestrationContext lépett
  • IDurableOrchestrationClient helyébe DurableTaskClient lépett
  • Frissített naplózás a DI vagy a FunctionContext
  • Futtatókörnyezettel local.settings.json frissítve dotnet-isolated
  • Az összes Microsoft.Azure.WebJobs.* eltávolítása utasítások használatával
  • Microsoft.Azure.Functions.Worker utasításokkal hozzáadva
  • A CreateEntityProxy<T> közvetlen CallEntityAsync, /, és SignalEntityAsync hívásokkal lett lecserélve.
  • Feladatközpontok közötti műveleti túlterhelések lecserélése (ha van használatban)
  • Kötegelt GetStatusAsync/PurgeInstanceHistoryAsync azonosítós hívásokat felváltva szűrőalapú vagy egyéni hívásokkal
  • Migrált DurableOrchestrationStatus.History hozzáférés a GetOrchestrationHistoryAsync
  • Frissített entitáskonstruktor-paramok DispatchAsync a DI használatához
  • Az összes függvény helyi tesztelése
  • Üzembe helyezve az előzetes helyen, majd ellenőrizve
  • Felcserélve az éles környezetbe

Következő lépések