Uw Durable Functions-app migreren van in-proces naar geïsoleerd werkrolmodel (.NET)

Deze handleiding begeleidt u bij het migreren van uw .NET Durable Functions-app van het in-procesmodel naar het geïsoleerde werkrolmodel. Het in-process model bereikt het einde van de ondersteuning op 10 november 2026. Na die datum worden er geen beveiligingsupdates of oplossingen voor fouten opgegeven. Het geïsoleerde werkrolmodel biedt u ook volledige procesbeheer, standaard .NET afhankelijkheidsinjectie en toegang tot de nieuwste platformfuncties.

Waarschuwing

De ondersteuning voor het in-process model eindigt op 10 november 2026. U wordt aangeraden nu te migreren. Zie .NET overzicht van geïsoleerde werkprocessen voor achtergrondinformatie over het geïsoleerde werkrolmodel.

Controlelijst voor migratie

Gebruik de volgende controlelijst om de voortgang van elke migratiestap bij te houden:

Stap Afdeling
Vereisten verifiëren Prerequisites
2. Het projectbestand bijwerken Het projectbestand bijwerken
3. Program.cs toevoegen Program.cs toevoegen
4. Pakketverwijzingen bijwerken Pakketverwijzingen bijwerken
5. Functiecode bijwerken Functiecode bijwerken
6. local.settings.json bijwerken local.settings.jsonbijwerken
7. Lokaal testen Lokaal testen
8. Implementeren in Azure Implementeren naar Azure

Vereiste voorwaarden

  • Azure Functions Core Tools v4.x of hoger
  • .NET 8.0 SDK (of uw doelversie van .NET)
  • Visual Studio 2022 of VS Code met Azure Functions extensie

Apps identificeren die moeten worden gemigreerd (optioneel)

Als u niet zeker weet welke apps het in-process model nog steeds gebruiken, voert u dit Azure PowerShell script uit:

$FunctionApps = Get-AzFunctionApp

$AppInfo = @{}

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

$AppInfo

Apps die als runtime worden weergegeven dotnet , maken gebruik van het in-process model. Apps die al dotnet-isolated gebruikmaken van het geïsoleerde werkrolmodel.

Het projectbestand bijwerken

Vóór (in behandeling)

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

Na (geïsoleerde werker)

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

De belangrijkste wijzigingen zijn het overschakelen naar een uitvoerbaar uitvoertype en het vervangen van alle Microsoft.Azure.WebJobs.*-pakketten door hun Microsoft.Azure.Functions.Worker.* equivalenten.

Program.cs toevoegen

Voor het geïsoleerde werkrolmodel is een Program.cs toegangspunt vereist. Maak dit bestand in de hoofdmap van uw project. Als u een FunctionsStartup class in Startup.cs hebt, verplaatst u die serviceregistraties naar het ConfigureServices blok en verwijdert u 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();

Pakketverwijzingen bijwerken

pakkettoewijzing Durable Functions

Pakket in behandeling Pakket voor geïsoleerde werknemer
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

Algemene mapping van extensiepakketten

In behandeling Geïsoleerde werkrol
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

Belangrijk

Verwijder verwijzingen naar Microsoft.Azure.WebJobs.* naamruimten en Microsoft.Azure.Functions.Extensions uit uw project.

Functiecode bijwerken

In deze sectie worden de codewijzigingen voor elk Durable Functions type beschreven. Ga naar de sectie voor de functietypen die uw app gebruikt:

Zie de API-verwijzing voor de volledige API-per-API-mapping.

Naamruimtewijzigingen

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

Wijzigingen in functiekenmerk

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

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

Wijzigingen in orchestratorfunctie

Voordat (In-Process):

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

Na (geïsoleerde werker):

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

Belangrijkste verschillen

Aspect In behandeling Geïsoleerde werknemer
Contexttype IDurableOrchestrationContext TaskOrchestrationContext
Logger ILogger-parameter context.CreateReplaySafeLogger()
Attribute [FunctionName] [Function]

Wijzigingen in de activiteitsfunctie

Voordat (In-Process):

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

Na (geïsoleerde werker):

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

Wijzigingen in clientfuncties

Voordat (In-Process):

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

Na (geïsoleerde werker):

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

Wijzigingen in clienttype

In behandeling Geïsoleerde werkrol
IDurableOrchestrationClient DurableTaskClient
StartNewAsync() ScheduleNewOrchestrationInstanceAsync()
CreateCheckStatusResponse() CreateCheckStatusResponseAsync()
HttpRequest / IActionResult HttpRequestData / HttpResponseData

Beleidswijzigingen opnieuw proberen

In-process gebruikt RetryOptions met CallActivityWithRetryAsync. De geïsoleerde werknemer gebruikt TaskOptions met de standaard CallActivityAsync.

Voordat (In-Process):

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

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

Na (geïsoleerde werker):

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

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

Wijzigingen in entiteitsfuncties

Voordat (In-Process):

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

Na (geïsoleerde werker):

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

Wijzigingen in foutengedrag

Bekijk deze wijzigingen voordat u de gemigreerde app test. Zie de API-referentie voor de volledige API-voor-API-overzicht.

Waarschuwing

Standaard serialisatie is gewijzigd: de geïsoleerde worker gebruikt standaard System.Text.Json in plaats van Newtonsoft.Json. Als uw orkestraties complexe objecten doorgeven, test de serialisatie zorgvuldig. Zie de verschillen in JSON-serialisatie voor configuratieopties.

Waarschuwing

ContinueAsNew-standaardwijziging: de standaardwaarde van de preserveUnprocessedEvents parameter is gewijzigd van false (2.x) in true (geïsoleerd). Als uw orkestratie gebruikmaakt van ContinueAsNew en afhankelijk is van niet-verwerkte gebeurtenissen die worden verwijderd, moet u expliciet preserveUnprocessedEvents: false doorgeven.

Opmerking

Standaardwijziging restartAsync: de standaardwaarde van de restartWithNewInstanceId parameter is gewijzigd van true (2.x) in false (geïsoleerd). Als uw code aanroept RestartAsync en afhankelijk is van een nieuwe exemplaar-id die wordt gegenereerd, geeft u expliciet door restartWithNewInstanceId: true.

Andere belangrijke wijzigingen:

  • Entiteitsproxy's die zijn verwijderd , CreateEntityProxy<T> zijn niet beschikbaar. Gebruik Entities.CallEntityAsync of Entities.SignalEntityAsync rechtstreeks.
  • Cross-task-hub-bewerkingen verwijderd — Overbelastingen die taskHubName/connectionName accepteerden zijn niet beschikbaar. Alleen bewerkingen met dezelfde taakhub worden ondersteund.
  • Orchestratiegeschiedenis verplaatst - DurableOrchestrationStatus.History bevindt zich niet meer op het statusobject. Gebruik DurableTaskClient.GetOrchestrationHistoryAsync.

local.settings.jsonbijwerken

De belangrijkste wijziging is het instellen van FUNCTIONS_WORKER_RUNTIME van dotnet naar dotnet-isolated:

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

Opmerking

De back-endconfiguratie van uw opslag (Azure Storage, MSSQL, Netherite of Durable Task Scheduler) wordt niet gewijzigd door de migratie. Bewaar uw bestaande opslaginstellingen.

Lokaal testen

Voer uw functie-app lokaal uit en controleer of alle indelingen, activiteiten en entiteiten correct werken.

func start

Functionaliteit controleren

Test de volgende scenario's indien van toepassing:

  1. Start een orchestratie met een HTTP-trigger
  2. De orkestratiestatus bewaken
  3. De uitvoeringsvolgorde van de activiteit controleren
  4. Entiteitsbewerkingen testen indien van toepassing
  5. Application Insights-telemetrie controleren

Implementeren in Azure

Implementatiesites gebruiken om downtime te minimaliseren:

  1. Maak een staging-slot voor uw functie-app.
  2. Configuratie van staging-site bijwerken:
    • Stel FUNCTIONS_WORKER_RUNTIME in op dotnet-isolated.
    • Werk indien nodig .NET stackversie bij.
  3. Gemigreerde code implementeren in de staging-slot.
  4. Test grondig in de staging-slot.
  5. Voer sleuvenwissel uit om wijzigingen naar productie te verplaatsen.

Toepassingsinstellingen bijwerken

In de Azure-portal of via CLI:

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

Stackconfiguratie bijwerken

Als u een andere .NET versie wilt gebruiken:

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

Veelvoorkomende migratieproblemen

Probleem: fouten bij het laden van assemblages

Symptoom:Could not load file or assembly Fouten.

Solution: Zorg ervoor dat u alle Microsoft.Azure.WebJobs.* pakketverwijzingen verwijdert en vervangt door geïsoleerde werkrolequivalenten.

Probleem: bindingskenmerk niet gevonden

Symptoom:The type or namespace 'QueueTrigger' could not be found

Oplossing: Voeg het juiste extensiepakket toe en werk bij met behulp van instructies:

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

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

Probleem: IDurableOrchestrationContext niet gevonden

Symptoom:The type or namespace 'IDurableOrchestrationContext' could not be found

Oplossing: Vervangen door TaskOrchestrationContext:

using Microsoft.DurableTask;

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

Probleem: verschillen in JSON-serialisatie

Symptoom: Serialisatiefouten of onverwachte gegevensindelingen

Oplossing: Het geïsoleerde model gebruikt System.Text.Json standaard. Serialisatie configureren in Program.cs:

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

Gebruik in plaats daarvan Newtonsoft.Json:

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

Probleem: Aangepaste serialisatie-instellingen migreren

Symptoom: U hebt IMessageSerializerSettingsFactory in het in-procesmodel gebruikt en hebt het equivalent in een geïsoleerde werker nodig.

Oplossing: Configureer de serialisatiefunctie op werkniveau in Program.cs. Zie de sectie behaviorale wijzigingen van de API-verwijzing en Serialisatie en persistentie in Durable Functions voor meer informatie.

Newtonsoft.Json gebruiken met aangepaste instellingen:

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

Opmerking

Deze aanpak vereist de Newtonsoft.Json en Azure.Core.Serialization NuGet-pakketten.

Checklist

Gebruik deze controlelijst om een volledige migratie te garanderen:

  • Projectbestand bijgewerkt met <OutputType>Exe</OutputType>
  • Microsoft.NET.Sdk.Functions vervangen door werkpakketten
  • Vervangen Microsoft.Azure.WebJobs.Extensions.DurableTask door geïsoleerd pakket
  • Gemaakt Program.cs met hostconfiguratie
  • Klasse verwijderd FunctionsStartup (indien aanwezig)
  • Alles [FunctionName] bijgewerkt naar [Function]
  • IDurableOrchestrationContext Vervangen doorTaskOrchestrationContext
  • IDurableOrchestrationClient Vervangen doorDurableTaskClient
  • Logboekregistratie bijgewerkt voor gebruik van DI of FunctionContext
  • Bijgewerkt local.settings.json met dotnet-isolated runtime-omgeving
  • Alle Microsoft.Azure.WebJobs.* met behulp van instructies verwijderd
  • Microsoft.Azure.Functions.Worker met behulp van instructies toegevoegd
  • CreateEntityProxy<T> Vervangen door directe CallEntityAsync/SignalEntityAsync aanroepen
  • Vervangen van overbelastingen bij huboperaties met meerdere taken (indien gebruikt)
  • Batch GetStatusAsync/PurgeInstanceHistoryAsync -by-ID-aanroepen vervangen door op filters gebaseerde of afzonderlijke aanroepen
  • Gemigreerde DurableOrchestrationStatus.History toegang tot GetOrchestrationHistoryAsync
  • Parameters voor entiteitsconstructor DispatchAsync bijgewerkt voor het gebruik van DI
  • Alle functies lokaal getest
  • Geïmplementeerd in staging-site en geverifieerd
  • Gewisseld naar productieomgeving

Volgende stappen