Dayanıklı İşlevler uygulamanızı işlem içi çalışan modelinden yalıtılmış çalışan modeline (.NET) geçirme

Bu kılavuz, .NET Dayanıklı İşlevler uygulamanızı işlem içi modelden yalıtılmış çalışan modeline geçirme konusunda size yol gösterir. Süreç içi model 10 Kasım 2026'da destek sonuna ulaşıyor. Bu tarihten sonra hiçbir güvenlik güncelleştirmesi veya hata düzeltmesi sağlanmadı. Yalıtılmış çalışan modeli ayrıca tam işlem denetimi, standart .NET bağımlılık ekleme ve en son platform özelliklerine erişim sağlar.

Uyarı

İşlem içi model desteği 10 Kasım 2026'da sona erer. Şimdi taşımanızı tavsiye ederiz. Yalıtılmış çalışan modelinin arka planı için bkz. .NET yalıtılmış çalışan işlemine genel bakış.

Geçiş denetim listesi

Her geçiş adımında ilerleme durumunuzu izlemek için aşağıdaki denetim listesini kullanın:

Step Bölüm
1. Önkoşulları doğrulama Ön koşullar
2. Proje dosyasını güncelleştirme Proje dosyasını güncelleştirme
3. Program.cs ekle Program.cs ekle
4. Paket başvurularını güncelleştirme Paket başvurularını güncelleştirme
5. İşlev kodunu güncelleştirme İşlev kodunu güncelleştirme
6. Güncelle local.settings.json Güncelle local.settings.json
7. Yerel olarak test edin Yerel olarak test edin
Azure'a dağıt Azure’a dağıtın

Önkoşullar

  • Azure İşlevleri Core Tools v4.x veya üzeri
  • .NET 8.0 SDK (veya hedef .NET sürümünüz)
  • Visual Studio 2022 veya Azure İşlevleri uzantılı VS Kodu

Geçirecek uygulamaları tanımlama (isteğe bağlı)

Hangi uygulamaların hala işlem içi modeli kullandığından emin değilseniz şu Azure PowerShell betiğini çalıştırın:

$FunctionApps = Get-AzFunctionApp

$AppInfo = @{}

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

$AppInfo

Çalışma zamanı olarak gösterilen dotnet uygulamalar işlem içi modeli kullanır. Görüntülenen dotnet-isolated uygulamalar zaten yalıtılmış çalışan modelini kullanır.

Proje dosyasını güncelleştirme

Önce (işlem içi)

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

Sonra (yalıtılmış çalışan)

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

Ana değişiklikler yürütülebilir bir çıkış türüne geçmek ve tüm Microsoft.Azure.WebJobs.* paketlerini Microsoft.Azure.Functions.Worker.* eşdeğerleriyle değiştirmektir.

Program.cs ekle

Yalıtılmış çalışan modeli bir Program.cs giriş noktası gerektirir. Bu dosyayı proje kökünüzde oluşturun. Bir FunctionsStartup sınıfınız varsa Startup.cs içinde, bu hizmet kayıtlarını ConfigureServices bloğuna taşıyın ve Startup.cs'i silin.

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

Paket başvurularını güncelleştirme

Dayanıklı İşlevler paket haritalama

İşlemdeki paket Yalıtılmış çalışan paketi
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

Ortak uzantı paketi eşlemesi

İşlemde Yalıtılmış çalışan
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

Önemli

Microsoft.Azure.WebJobs.* ad alanlarına ve Microsoft.Azure.Functions.Extensions başvurularını projenizden kaldırın.

İşlev kodunu güncelleştirme

Bu bölüm, her Dayanıklı İşlevler türü için kod değişikliklerini kapsar. Uygulamanızın kullandığı işlev türlerinin bölümüne atlayın:

TAM API'ye göre eşleme için bkz. API başvurusu.

Ad alanı değişiklikleri

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

İşlev özniteliği değişiklikleri

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

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

Orchestrator fonksiyonu değişiklikleri

Önce (İşlem İçinde):

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

Sonra (Yalıtılmış Çalışan):

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

Önemli farklar

Görünüş İşlemde Yalıtılmış Çalışan
Bağlam türü IDurableOrchestrationContext TaskOrchestrationContext
Logger ILogger parametresi context.CreateReplaySafeLogger()
Özellik [FunctionName] [Function]

Etkinlik işlevi değişiklikleri

Önce (İşlem İçinde):

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

Sonra (Yalıtılmış Çalışan):

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

İstemci işlevi değişiklikleri

Önce (İşlem İçinde):

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

Sonra (Yalıtılmış Çalışan):

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

İstemci türü değişiklikleri

İşlemde Yalıtılmış çalışan
IDurableOrchestrationClient DurableTaskClient
StartNewAsync() ScheduleNewOrchestrationInstanceAsync()
CreateCheckStatusResponse() CreateCheckStatusResponseAsync()
HttpRequest / IActionResult HttpRequestData / HttpResponseData

İlke değişikliklerini yeniden deneme

İşlem içi kullanımlar RetryOptions ile CallActivityWithRetryAsync yapılır. Yalıtılmış çalışan TaskOptions’yi standart CallActivityAsync ile kullanır.

Önce (İşlem İçinde):

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

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

Sonra (Yalıtılmış Çalışan):

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

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

Varlık işlevi değişiklikleri

Önce (İşlem İçinde):

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

Sonra (Yalıtılmış Çalışan):

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

Uyumluluğu bozan davranış değişiklikleri

Geçirilen uygulamanızı test etmeden önce bu değişiklikleri gözden geçirin. API'ye göre API eşlemesinin tamamı için bkz. API başvurusu.

Uyarı

Serileştirme varsayılanı değiştirildi: Yalıtılmış çalışan varsayılan olarak yerine System.Text.JsonkullanırNewtonsoft.Json. Orkestrasyonlarınız karmaşık nesneler aktarıyorsa, serileştirmeyi dikkatle test edin. Yapılandırma seçenekleri için bkz. JSON serileştirme farklılıkları .

Uyarı

ContinueAsNew varsayılan değişikliği: Parametre preserveUnprocessedEvents varsayılanı (2.x) olan false (yalıtılmış) true olarak değiştirildi. Düzenlemeniz ContinueAsNew kullanıyorsa ve işlenmemiş olayların atılmasına bağlıysa, açıkça preserveUnprocessedEvents: false'i geçirmeniz gerek.

Uyarı

RestartAsync varsayılan değişikliği: Parametre restartWithNewInstanceId varsayılanı (2.x) olan true (yalıtılmış) false olarak değiştirildi. Kodunuz RestartAsync çağırırsa ve bu, yeni bir örnek kimliğinin oluşturulmasına bağlıysa, restartWithNewInstanceId: true'i açıkça geçirin.

Diğer önemli değişiklikler:

  • Varlık proxy'leri kaldırıldıCreateEntityProxy<T> kullanılamaz. Entities.CallEntityAsync Veya doğrudan kullanınEntities.SignalEntityAsync.
  • Görevler arası hub operasyonları kaldırıldı — Kabul edilen taskHubName/connectionName çoklu yüklenmeler artık kullanılamaz. Yalnızca aynı görev merkezli hub işlemleri desteklenir.
  • Orkestrasyon geçmişi taşındıDurableOrchestrationStatus.History artık durum nesnesinde değil. DurableTaskClient.GetOrchestrationHistoryAsync adresini kullanın.

Güncelle local.settings.json

Anahtar değişiklik, FUNCTIONS_WORKER_RUNTIME öğesini dotnet yerine dotnet-isolated olarak ayarlamaktır.

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

Uyarı

Depolama arka uç yapılandırmanız (Azure Depolama, MSSQL, Netherite veya Dayanıklı Görev Zamanlayıcı) geçiş tarafından değiştirilmez. Depolamayla ilgili mevcut ayarlarınızı koruyun.

Yerel olarak test et

İşlev uygulamanızı yerel olarak çalıştırın ve tüm düzenlemelerin, etkinliklerin ve varlıkların düzgün çalıştığını doğrulayın.

func start

İşlevselliği doğrulama

Aşağıdaki senaryoları uygun şekilde test edin:

  1. HTTP tetikleyicisi ile bir orkestrasyon başlatın
  2. Orkestrasyon durumunu izle
  3. Etkinlik yürütme sırasını doğrulama
  4. Varsa varlık işlemlerini test edin
  5. Application Insights telemetri verilerini denetleme

Azure’a dağıtın

Kapalı kalma süresini en aza indirmek için dağıtım yuvalarını kullanın:

  1. İşlev uygulamanız için bir hazırlama yuvası oluşturun.
  2. Hazırlama yuvası yapılandırmasını güncelleştirme:
    • FUNCTIONS_WORKER_RUNTIME seçeneğini dotnet-isolated olarak ayarlayın.
    • Gerekirse .NET yığını sürümünü güncelleştirin.
  3. Geçirilen kodu hazırlama yuvasına dağıtın.
  4. Hazırlama yuvasında kapsamlı bir şekilde test edin.
  5. Değişiklikleri üretime taşımak için slot swap yapın.

Uygulama ayarlarını güncelleştirme

Azure portalında veya CLI aracılığıyla:

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

Yığın yapılandırmasını güncelleştir

Farklı bir .NET sürümü hedefleniyorsa:

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

Genel geçiş sorunları

Sorun: Derleme yükleme hataları

Belirti:Could not load file or assembly Hata.

Solution: Tüm Microsoft.Azure.WebJobs.* paket başvurularını kaldırdığınızdan ve bunları yalıtılmış çalışan eşdeğerleriyle değiştirdiğinizden emin olun.

Sorun: Bağlama özniteliği bulunamadı

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

Çözüm: Uygun uzantı paketini ekleyin ve "using" ifadelerini güncelleyin:

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

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

Sorun: IDurableOrchestrationContext bulunamadı

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

Çözüm: değerini ile TaskOrchestrationContextdeğiştirin:

using Microsoft.DurableTask;

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

Sorun: JSON serileştirme farklılıkları

Belirti: Serileştirme hataları veya beklenmeyen veri biçimleri

Çözüm: Yalıtılmış model varsayılan olarak kullanır System.Text.Json . Serileştirmeyi Program.cs içinde yapılandırın.

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

Bunun yerine Newtonsoft.Json'ı kullanmak için:

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

Sorun: Özel serileştirme ayarlarını geçirme

Belirti: İşlem içi modelde IMessageSerializerSettingsFactory kullandınız ve yalıtılmış çalışma konumunda eşdeğerine ihtiyacınız var.

Çözüm:Program.cs içinde işçi seviyesinde serileştiriciyi yapılandırın. Ayrıntılar için API başvurusunun behavioral changes bölümüne ve Serialization and persistence in Dayanıklı İşlevler bölümüne bakın.

Newtonsoft.Json'ı özel ayarlarla kullanmak için:

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

Uyarı

Bu yaklaşım Newtonsoft.Json ve Azure.Core.Serialization NuGet paketlerini gerektirir.

Checklist

Tam geçiş sağlamak için bu denetim listesini kullanın:

  • proje dosyası <OutputType>Exe</OutputType> yardımıyla güncellendi
  • Microsoft.NET.Sdk.Functions işçi paketleriyle değiştirildi
  • Microsoft.Azure.WebJobs.Extensions.DurableTask yalıtılmış paketle değiştirildi
  • Host yapılandırmasıyla oluşturuldu Program.cs
  • Sınıf kaldırıldı FunctionsStartup (varsa)
  • Tümü [FunctionName] şu şekilde güncelleştirildi: [Function]
  • IDurableOrchestrationContext TaskOrchestrationContext ile değiştirildi
  • IDurableOrchestrationClient DurableTaskClient ile değiştirildi
  • Günlükler, Bağımlılık Enjeksiyonu (DI) veya FunctionContext kullanacak şekilde güncellendi.
  • local.settings.json, dotnet-isolated çalışma zamanı ile güncellendi
  • Tüm Microsoft.Azure.WebJobs.* using ifadeleri kaldırıldı
  • using ifadeleri kullanılarak Microsoft.Azure.Functions.Worker eklenmesi
  • CreateEntityProxy<T> doğrudan CallEntityAsync/SignalEntityAsync çağrılarla değiştirildi
  • Görev-hub'lar arası işlem aşırı yüklemeleri değiştirildi (kullanılıyorsa)
  • Toplu by-ID GetStatusAsync/PurgeInstanceHistoryAsync çağrıları filtre tabanlı veya tek tek çağrılarla değiştirildi
  • DurableOrchestrationStatus.History erişimi GetOrchestrationHistoryAsync'ye geçirildi
  • VARLıK DispatchAsync oluşturucu parametreleri DI kullanacak şekilde güncelleştirildi
  • Tüm işlevler yerel olarak test edildi
  • Hazırlama yuvasına dağıtıldı ve doğrulandı
  • Üretime değiştirildi

Sonraki Adımlar