Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Panduan ini memandu Anda memigrasikan aplikasi .NET Durable Functions dari model dalam proses ke model pekerja yang terisolasi. Model dalam proses mencapai akhir dukungan pada 10 November 2026. Setelah tanggal tersebut, tidak ada pembaruan keamanan atau perbaikan bug yang disediakan. Model pekerja yang terisolasi juga memberi Anda kontrol proses penuh, injeksi dependensi .NET standar, dan akses ke fitur platform terbaru.
Warning
Dukungan untuk model dalam proses berakhir pada 10 November 2026. Kami menyarankan untuk migrasi sekarang. Untuk latar belakang model pekerja terisolasi, lihat gambaran umum proses pekerja .NET terisolasi.
Daftar periksa migrasi
Gunakan daftar periksa berikut untuk melacak kemajuan Anda melalui setiap langkah migrasi:
| Step | Section |
|---|---|
| 1. Verifikasi prasyarat | Prasyarat |
| 2. Perbarui file proyek | Memperbarui file proyek |
| 3. Tambahkan Program.cs | Tambahkan Program.cs |
| 4. Memperbarui referensi paket | Memperbarui referensi paket |
| 5. Perbarui kode fungsi | Memperbarui kode fungsi |
| 6. Perbarui local.settings.json | Memperbarui local.settings.json |
| 7. Uji secara lokal | Uji secara lokal |
| 8. Sebarkan ke Azure | Sebarkan ke Azure |
Prasyarat
- Azure Functions Core Tools v4.x atau yang lebih baru
- .NET 8.0 SDK (atau versi .NET target Anda)
- Visual Studio 2022 atau VS Code dengan ekstensi Azure Functions
Mengidentifikasi aplikasi untuk dimigrasikan (opsional)
Jika Anda tidak yakin aplikasi mana yang masih menggunakan model dalam proses, jalankan skrip Azure PowerShell ini:
$FunctionApps = Get-AzFunctionApp
$AppInfo = @{}
foreach ($App in $FunctionApps)
{
if ($App.Runtime -eq 'dotnet')
{
$AppInfo.Add($App.Name, $App.Runtime)
}
}
$AppInfo
Aplikasi yang menampilkan dotnet sebagai waktu proses menggunakan model in-process. Aplikasi yang menunjukkan dotnet-isolated sudah menggunakan model pekerja yang terisolasi.
Memperbarui file proyek
Sebelum (dalam proses)
<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>
Setelah (pekerja terisolasi)
<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>
Perubahan utama adalah beralih ke jenis output yang dapat dieksekusi dan mengganti semua paket Microsoft.Azure.WebJobs.* dengan paket Microsoft.Azure.Functions.Worker.* yang setara.
Tambahkan Program.cs
Model pekerja terisolasi memerlukan Program.cs titik masuk. Buat file ini di akar proyek Anda. Jika Anda memiliki FunctionsStartup kelas di Startup.cs, pindahkan blok pendaftaran layanan tersebut ke ConfigureServices dan hapus 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();
Memperbarui referensi paket
pemetaan paket Durable Functions
| Paket dalam proses | Paket pekerja terisolasi |
|---|---|
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 |
Pemetaan paket ekstensi umum
| Sedang dalam proses | Pekerja terisolasi |
|---|---|
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
Hapus referensi apa pun ke namespace Microsoft.Azure.WebJobs.* dan Microsoft.Azure.Functions.Extensions dari proyek Anda.
Memperbarui kode fungsi
Bagian ini mencakup perubahan kode untuk setiap jenis Durable Functions. Lompat ke bagian untuk jenis fungsi yang digunakan aplikasi Anda:
- Perubahan namespace
- Fungsi orkestrator
- Fungsi aktivitas
- Fungsi klien
- Kebijakan pengulangan (jika digunakan)
- Fungsi entitas (jika digunakan)
Untuk pemetaan API-by-API lengkap, lihat referensi API.
Perubahan namespace
// 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;
Perubahan atribut fungsi
// Before (In-Process)
[FunctionName("MyOrchestrator")]
// After (Isolated Worker)
[Function(nameof(MyOrchestrator))]
Perubahan fungsi orkestrator
Sebelum (Dalam Proses):
[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 };
}
Setelah (Pekerja Terisolasi):
[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 };
}
Perbedaan utama
| Aspek | Sedang Diproses | Pekerja Terisolasi |
|---|---|---|
| Jenis konteks | IDurableOrchestrationContext |
TaskOrchestrationContext |
| Logger |
ILogger parameter |
context.CreateReplaySafeLogger() |
| Atribut | [FunctionName] |
[Function] |
Perubahan pada fungsi aktivitas
Sebelum (Dalam Proses):
[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;
}
Setelah (Pekerja Terisolasi):
[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;
}
Perubahan fungsi klien
Sebelum (Dalam Proses):
[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);
}
Setelah (Pekerja Terisolasi):
[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);
}
Perubahan jenis klien
| Sedang dalam proses | Pekerja terisolasi |
|---|---|
IDurableOrchestrationClient |
DurableTaskClient |
StartNewAsync() |
ScheduleNewOrchestrationInstanceAsync() |
CreateCheckStatusResponse() |
CreateCheckStatusResponseAsync() |
HttpRequest / IActionResult |
HttpRequestData / HttpResponseData |
Mencoba kembali perubahan kebijakan
Proses ini menggunakan RetryOptions dengan CallActivityWithRetryAsync. Pekerja yang terisolasi menggunakan TaskOptions dengan standar CallActivityAsync.
Sebelum (Dalam Proses):
var retryOptions = new RetryOptions(
firstRetryInterval: TimeSpan.FromSeconds(5),
maxNumberOfAttempts: 3);
string result = await context.CallActivityWithRetryAsync<string>(
"MyActivity", retryOptions, input);
Setelah (Pekerja Terisolasi):
var retryOptions = new TaskOptions(
new TaskRetryOptions(new RetryPolicy(
maxNumberOfAttempts: 3,
firstRetryInterval: TimeSpan.FromSeconds(5))));
string result = await context.CallActivityAsync<string>(
"MyActivity", input, retryOptions);
Perubahan fungsi entitas
Sebelum (Dalam Proses):
[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;
}
}
Setelah (Pekerja Terisolasi):
[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;
}
Perubahan perilaku yang berdampak signifikan
Tinjau perubahan ini sebelum menguji aplikasi yang dimigrasikan. Untuk pemetaan API-by-API lengkap, lihat referensi API.
Warning
Default serialisasi berubah: Pekerja yang terisolasi menggunakan System.Text.Json secara default alih-alih Newtonsoft.Json. Jika orkestrasi Anda melewati objek yang kompleks, uji serialisasi dengan hati-hati. Lihat Perbedaan serialisasi JSON untuk opsi konfigurasi.
Warning
Perubahan default ContinueAsNew: Parameter preserveUnprocessedEvents default berubah dari false (2.x) menjadi true (terisolasi). Jika orkestrasi Anda menggunakan ContinueAsNew dan mengandalkan pembuangan peristiwa yang tidak diproses, operasikan secara eksplisit preserveUnprocessedEvents: false.
Note
Perubahan default RestartAsync: Parameter restartWithNewInstanceId default berubah dari true (2.x) menjadi false (terisolasi). Jika kode Anda memanggil RestartAsync dan bergantung pada ID instans baru yang dihasilkan, berikan secara eksplisit restartWithNewInstanceId: true.
Perubahan penting lainnya:
-
Proksi entitas dihapus —
CreateEntityProxy<T>tidak tersedia. GunakanEntities.CallEntityAsyncatauEntities.SignalEntityAsyncsecara langsung. -
Operasi hub lintas tugas dihapus — Kelebihan beban yang diterima
taskHubName/connectionNametidak tersedia. Hanya operasi hub tugas yang sama yang didukung. -
Riwayat orkestrasi telah dipindahkan —
DurableOrchestrationStatus.Historytidak lagi terdapat dalam objek status. GunakanDurableTaskClient.GetOrchestrationHistoryAsync.
Memperbarui local.settings.json
Perubahan kunci adalah pengaturan FUNCTIONS_WORKER_RUNTIME dari dotnet ke dotnet-isolated:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
}
}
Note
Konfigurasi backend penyimpanan Anda (Azure Storage, MSSQL, Netherite, atau Durable Task Scheduler) tidak berubah oleh migrasi. Pertahankan pengaturan terkait penyimpanan yang ada.
Uji secara lokal
Jalankan aplikasi fungsi Anda secara lokal dan verifikasi semua orkestrasi, aktivitas, dan entitas berfungsi dengan benar.
func start
Memverifikasi fungsionalitas
Uji skenario berikut sebagaimana berlaku:
- Memulai orkestrasi dengan pemicu HTTP
- Pemantauan status dari orkestrasi
- Memverifikasi urutan eksekusi aktivitas
- Menguji operasi entitas jika berlaku
- Periksa telemetri pada Application Insights
Sebarkan ke Azure
Disarankan: Gunakan slot penyebaran
Gunakan slot penyebaran untuk meminimalkan waktu henti:
- Buat slot pengujian aplikasi fungsi Anda.
-
Memperbarui konfigurasi slot penahapan:
- Atur
FUNCTIONS_WORKER_RUNTIMEkedotnet-isolated. - Perbarui versi tumpukan .NET jika diperlukan.
- Atur
- Sebarkan kode yang dimigrasikan ke slot staging.
- Uji secara menyeluruh di slot penahapan.
- Lakukan pertukaran slot untuk memindahkan perubahan ke produksi.
Memperbarui pengaturan aplikasi
Di portal Azure atau melalui CLI:
az functionapp config appsettings set \
--name <FUNCTION_APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--settings FUNCTIONS_WORKER_RUNTIME=dotnet-isolated
Memperbarui konfigurasi tumpukan
Jika menargetkan versi .NET yang berbeda:
az functionapp config set \
--name <FUNCTION_APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--net-framework-version v8.0
Masalah migrasi umum
Masalah: Kesalahan pemuatan rakitan
Gejala:Could not load file or assembly Kesalahan.
Solusi: Pastikan Anda menghapus semua referensi paket Microsoft.Azure.WebJobs.* dan menggantinya dengan pekerja terisolasi yang setara.
Masalah: Atribut pengikatan tidak ditemukan
Gejala:The type or namespace 'QueueTrigger' could not be found
Solusi: Tambahkan paket ekstensi yang sesuai dan perbarui menggunakan pernyataan:
// Add using statement
using Microsoft.Azure.Functions.Worker;
// Install package
// dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues
Masalah: IDurableOrchestrationContext tidak ditemukan
Gejala:The type or namespace 'IDurableOrchestrationContext' could not be found
Solusi: Ganti dengan TaskOrchestrationContext:
using Microsoft.DurableTask;
[Function(nameof(MyOrchestrator))]
public static async Task MyOrchestrator([OrchestrationTrigger] TaskOrchestrationContext context)
{
// ...
}
Masalah: Perbedaan serialisasi JSON
Gejala: Kesalahan serialisasi atau format data yang tidak terduga
Solusi: Model terisolasi menggunakan System.Text.Json secara default. Konfigurasikan serialisasi di Program.cs:
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices(services => {
services.Configure<JsonSerializerOptions>(options => {
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
})
.Build();
Untuk menggunakan Newtonsoft.Json sebagai gantinya:
services.Configure<WorkerOptions>(options => {
options.Serializer = new NewtonsoftJsonObjectSerializer();
});
Masalah: Memigrasikan pengaturan serialisasi kustom
Gejala: Anda menggunakan IMessageSerializerSettingsFactory dalam model dalam proses dan memerlukan yang setara dalam pekerja terisolasi.
Solusi: Konfigurasikan serializer tingkat pekerja di Program.cs. Untuk detailnya, lihat bagian perubahan perilaku referensi API dan Serialisasi serta persistensi dalam Durable Functions.
Untuk menggunakan Newtonsoft.Json dengan pengaturan kustom:
// 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
Pendekatan ini memerlukan paket NuGet Newtonsoft.Json dan Azure.Core.Serialization.
Checklist
Gunakan daftar periksa ini untuk memastikan migrasi lengkap:
- File proyek yang diperbarui dengan
<OutputType>Exe</OutputType> - Mengganti
Microsoft.NET.Sdk.Functionsdengan paket worker - Mengganti
Microsoft.Azure.WebJobs.Extensions.DurableTaskdengan paket terisolasi - Dibuat
Program.csmenggunakan konfigurasi host - Kelas yang dihapus
FunctionsStartup(jika ada) - Diperbarui semua
[FunctionName]ke[Function] - Diganti
IDurableOrchestrationContextdenganTaskOrchestrationContext - Diganti
IDurableOrchestrationClientdenganDurableTaskClient - Pengelogan yang diperbarui untuk menggunakan DI atau
FunctionContext - Diperbarui
local.settings.jsondengandotnet-isolatedruntime - Menghapus semua
Microsoft.Azure.WebJobs.*menggunakan pernyataan - Menambahkan
Microsoft.Azure.Functions.Workermenggunakan pernyataan - Diganti
CreateEntityProxy<T>dengan panggilan langsungCallEntityAsync/SignalEntityAsync - Penggantian beban overload operasi cross-task-hub (jika digunakan)
- Mengganti panggilan berbasis ID batch
GetStatusAsync/PurgeInstanceHistoryAsyncdengan panggilan berbasis filter atau berbasis individu - Pemindahan akses
DurableOrchestrationStatus.HistorykeGetOrchestrationHistoryAsync - Param konstruktor entitas
DispatchAsyncyang diperbarui untuk menggunakan DI - Menguji semua fungsi secara lokal
- Telah diterapkan ke slot staging dan diverifikasi
- Dipindahkan ke produksi
Langkah berikutnya
- Pemetaan API dari pekerja dalam proses ke pekerja yang terisolasi — referensi API lengkap untuk migrasi Anda
- ringkasan tentang Durable Functions untuk pekerja terisolasi .NET
- Versi Durable Functions dan panduan migrasi
Konten terkait
- Panduan migrasi resmi Microsoft (semua Azure Functions)
- gambaran umum proses pekerja terisolasi .NET
- Perbedaan model pekerja terisolasi
- Serialisasi dan persistensi dalam Durable Functions
- penyebaran tanpa waktu henti untuk Durable Functions
- Mengonfigurasi Durable Task Scheduler