Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этом руководстве описывается перенос приложения .NET Устойчивые функции из модели внутрипроцессной в изолированную рабочую модель. Модель в процессе утратит поддержку 10 ноября 2026 г. После этой даты обновления системы безопасности или исправления ошибок не предоставляются. Изолированная рабочая модель также предоставляет полный контроль над процессами, стандартное внедрение зависимостей .NET и доступ к новейшим функциям платформы.
Предупреждение
Поддержка модели в процессе заканчивается 10 ноября 2026 г. Мы рекомендуем начать миграцию сейчас. Общие сведения об изолированной рабочей модели см. в разделе .NET обзор изолированного рабочего процесса.
Контрольный список миграции
Используйте следующий контрольный список для отслеживания хода выполнения каждого шага миграции:
| Step | Секция |
|---|---|
| 1. Проверка предварительных требований | Prerequisites |
| 2. Обновление файла проекта | Обновление файла проекта |
| Добавьте Program.cs | Добавить Program.cs |
| 4. Обновление ссылок на пакет | Обновление ссылок на пакет |
| 5. Обновление кода функции | Обновление кода функции |
| 6. Обновление local.settings.json | Обновление local.settings.json |
| 7. Локальное тестирование | Локальное тестирование |
| 8. Развертывание в Azure | Развертывание в Azure |
Необходимые условия
- Функции Azure Core Tools версии 4.x или более поздней версии
- пакет SDK .NET 8.0 (или целевая версия .NET)
- Visual Studio 2022 или VS Code с расширением Функции Azure
Определение приложений для миграции (необязательно)
Если вы не уверены, какие приложения по-прежнему используют модель в процессе, запустите этот скрипт Azure PowerShell:
$FunctionApps = Get-AzFunctionApp
$AppInfo = @{}
foreach ($App in $FunctionApps)
{
if ($App.Runtime -eq 'dotnet')
{
$AppInfo.Add($App.Name, $App.Runtime)
}
}
$AppInfo
Приложения, которые используют dotnet в качестве среды выполнения, используют внутрипроцессную модель. Приложения, которые показывают dotnet-isolated, уже используют изолированную рабочую модель.
Обновление файла проекта
До (в процессе)
<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>
После (изолированный рабочий)
<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>
Основные изменения состоят в переходе на исполняемый тип выходных данных и замене всех пакетов Microsoft.Azure.WebJobs.* их эквивалентами Microsoft.Azure.Functions.Worker.*.
Добавьте Program.cs
Для изолированной рабочей модели требуется Program.cs точка входа. Создайте этот файл в корневом каталоге проекта. Если у вас есть FunctionsStartup класс Startup.cs, переместите эти регистрации служб в ConfigureServices блок и удалите 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();
Обновление ссылок на пакет
сопоставление пакетов Устойчивые функции
| Внутрипроцессный пакет | Пакет изолированного работника |
|---|---|
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 |
Общее сопоставление пакетов расширений
| В процессе | Изолированный работник |
|---|---|
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
Удалите все ссылки на пространства имен Microsoft.Azure.WebJobs.* и Microsoft.Azure.Functions.Extensions из проекта.
Обновление кода функции
В этом разделе рассматриваются изменения кода для каждого типа Устойчивые функции. Перейдите к разделу для типов функций, которые использует приложение:
- Изменения пространства имен
- Функции Оркестратора
- Функции действий
- Клиентские функции
- Политики повторных попыток (при использовании)
- Функции сущности (при использовании)
Полное сопоставление API по API см. в справочнике по API.
Изменения пространства имен
// 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;
Изменения атрибута функции
// Before (In-Process)
[FunctionName("MyOrchestrator")]
// After (Isolated Worker)
[Function(nameof(MyOrchestrator))]
Изменения функции Orchestrator
До (в процессе):
[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 };
}
После изолированного работника:
[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 };
}
Основные отличия
| Аспект | В процессе | Изолированный работник |
|---|---|---|
| Тип контекста | IDurableOrchestrationContext |
TaskOrchestrationContext |
| Logger |
ILogger Параметр |
context.CreateReplaySafeLogger() |
| Атрибут | [FunctionName] |
[Function] |
Изменения функции активности
До (в процессе):
[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;
}
После изолированного работника:
[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;
}
Изменения функции клиента
До (в процессе):
[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);
}
После изолированного работника:
[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);
}
Изменения типа клиента
| В процессе | Изолированный работник |
|---|---|
IDurableOrchestrationClient |
DurableTaskClient |
StartNewAsync() |
ScheduleNewOrchestrationInstanceAsync() |
CreateCheckStatusResponse() |
CreateCheckStatusResponseAsync() |
HttpRequest / IActionResult |
HttpRequestData / HttpResponseData |
Изменения политики повторных попыток
В процессе используется RetryOptions с CallActivityWithRetryAsync. Изолированный работник использует TaskOptions со стандартом CallActivityAsync.
До (в процессе):
var retryOptions = new RetryOptions(
firstRetryInterval: TimeSpan.FromSeconds(5),
maxNumberOfAttempts: 3);
string result = await context.CallActivityWithRetryAsync<string>(
"MyActivity", retryOptions, input);
После изолированного работника:
var retryOptions = new TaskOptions(
new TaskRetryOptions(new RetryPolicy(
maxNumberOfAttempts: 3,
firstRetryInterval: TimeSpan.FromSeconds(5))));
string result = await context.CallActivityAsync<string>(
"MyActivity", input, retryOptions);
Изменения функции сущности
До (в процессе):
[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;
}
}
После изолированного работника:
[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;
}
Изменения, нарушающие поведение
Просмотрите эти изменения перед тестированием перенесенного приложения. Полный сопоставление API по API см. в справочнике по API.
Предупреждение
Сериализация по умолчанию изменена: изолированный рабочий по умолчанию использует System.Text.Json вместо Newtonsoft.Json. Если в ваших оркестрациях передаются сложные объекты, тщательно проверьте сериализацию. См. различия сериализации JSON для параметров конфигурации.
Предупреждение
Продолжение изменения по умолчанию для AsNew: preserveUnprocessedEvents параметр по умолчанию изменился с false (2.x) на true (изолированный). Если ваша оркестрация использует ContinueAsNew и зависит от сброса необработанных событий, передайте preserveUnprocessedEvents: false явно.
Note
Изменение параметра по умолчанию для RestartAsync: restartWithNewInstanceId параметр по умолчанию был изменён с true (2.x) на false (изолированный). Если ваш код вызывает RestartAsync и зависит от создания нового идентификатора экземпляра, явно передайте restartWithNewInstanceId: true.
Другие заметные изменения:
-
Прокси-серверы сущностей удалены —
CreateEntityProxy<T>недоступен. ИспользуйтеEntities.CallEntityAsyncилиEntities.SignalEntityAsyncнапрямую. -
Удалены операции в узле задач — перегрузки, которые приняты
taskHubName/connectionName, недоступны. Поддерживаются только те же операции центра задач. -
Журнал оркестрации перемещен —
DurableOrchestrationStatus.Historyбольше не находится в объекте состояния. ИспользуйтеDurableTaskClient.GetOrchestrationHistoryAsync.
Обновите local.settings.json
Ключевое изменение заключается в установке FUNCTIONS_WORKER_RUNTIME с dotnet на dotnet-isolated:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
}
}
Note
Конфигурация серверной части хранилища (служба хранилища Azure, MSSQL, Netherite или планировщик устойчивых задач) не изменяется при миграции. Сохраните существующие параметры, связанные с хранилищем.
Локальное тестирование
Запустите функциональное приложение локально и убедитесь, что все оркестрации, действия и сущности работают корректно.
func start
Проверка функциональности
Проверьте следующие сценарии, как применимо:
- Запуск оркестрации с помощью триггера HTTP
- Мониторинг состояния оркестрации
- Проверка порядка выполнения действия
- Проверка операций сущностей, если применимо
- Проверьте телеметрию Application Insights
Развертывание в Azure
Рекомендуется: использовать слоты развертывания
Используйте слоты развертывания, чтобы свести к минимуму время простоя:
- Создайте промежуточный слот для приложения-функции.
-
Обновление конфигурации промежуточного слота:
- Установите
FUNCTIONS_WORKER_RUNTIMEнаdotnet-isolated. - При необходимости обновите версию стека .NET.
- Установите
- Разверните перенесенный код в промежуточный слот.
- Тщательно протестируйте в промежуточном слоте.
- Выполните обмен слотов для переноса изменений в производственную среду.
Обновление параметров приложения
На портале Azure или через CLI:
az functionapp config appsettings set \
--name <FUNCTION_APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--settings FUNCTIONS_WORKER_RUNTIME=dotnet-isolated
Обновление конфигурации стека
Если нацеливаетесь на другую версию .NET:
az functionapp config set \
--name <FUNCTION_APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--net-framework-version v8.0
Распространенные проблемы с миграцией
Проблема: ошибки загрузки сборки
Симптом:Could not load file or assembly Ошибки.
Solution: Убедитесь, что удалите все ссылки на пакеты Microsoft.Azure.WebJobs.* и замените их изолированными рабочими эквивалентами.
Проблема: атрибут привязки не найден
Симптом:The type or namespace 'QueueTrigger' could not be found
Решение: Добавьте соответствующий пакет расширения и обновите инструкции using:
// Add using statement
using Microsoft.Azure.Functions.Worker;
// Install package
// dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues
Проблема: IDurableOrchestrationContext не найден
Симптом:The type or namespace 'IDurableOrchestrationContext' could not be found
Решение: Замените на TaskOrchestrationContext:
using Microsoft.DurableTask;
[Function(nameof(MyOrchestrator))]
public static async Task MyOrchestrator([OrchestrationTrigger] TaskOrchestrationContext context)
{
// ...
}
Проблема: различия сериализации JSON
Симптом: Ошибки сериализации или непредвиденные форматы данных
Решение: Изолированная модель используется System.Text.Json по умолчанию. Настройка сериализации в Program.cs:
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices(services => {
services.Configure<JsonSerializerOptions>(options => {
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
})
.Build();
Чтобы использовать Newtonsoft.Json, вместо этого выполните приведенные далее действия.
services.Configure<WorkerOptions>(options => {
options.Serializer = new NewtonsoftJsonObjectSerializer();
});
Проблема. Перенос пользовательских параметров сериализации
Симптом: Вы используете IMessageSerializerSettingsFactory во внутрипроцессной модели и нуждаетесь в эквиваленте в изолированном рабочем процессе.
Решение: Настройте сериализатор на уровне воркера в Program.cs. Дополнительные сведения см. в разделе behavioral changes справочника по API и Сериализация и сохраняемость в Устойчивые функции.
Чтобы использовать Newtonsoft.Json с настраиваемыми параметрами, выполните следующие действия.
// 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
Для этого подхода требуются пакеты NuGet Newtonsoft.Json и Azure.Core.Serialization.
Checklist
Используйте этот контрольный список, чтобы обеспечить полную миграцию:
- Обновленный файл проекта с помощью
<OutputType>Exe</OutputType> - Заменили
Microsoft.NET.Sdk.Functionsна рабочие пакеты - Заменено
Microsoft.Azure.WebJobs.Extensions.DurableTaskизолированным пакетом - Создано
Program.csс конфигурацией хоста - Удален
FunctionsStartupкласс (при наличии) - Обновлено все
[FunctionName]до[Function] - Заменено
IDurableOrchestrationContextнаTaskOrchestrationContext - Заменено
IDurableOrchestrationClientнаDurableTaskClient - Обновлено ведение журнала для использования DI или
FunctionContext - Обновлено
local.settings.jsonс помощьюdotnet-isolatedсреды выполнения - Удалены все операторы
Microsoft.Azure.WebJobs.*using - Добавлено
Microsoft.Azure.Functions.Workerс помощью инструкций -
CreateEntityProxy<T>Заменено прямымиCallEntityAsync/SignalEntityAsyncвызовами - Заменены перегрузки операций в концентраторе задач (если используются)
- Заменены пакетные вызовы
GetStatusAsync/PurgeInstanceHistoryAsyncпо ID на вызовы, основанные на фильтрах, или на отдельные вызовы. - Перенос доступа
DurableOrchestrationStatus.HistoryкGetOrchestrationHistoryAsync - Обновлены параметры конструктора сущности
DispatchAsyncдля использования внедрения зависимостей (DI) - Тестирование всех функций локально
- Развернуто в промежуточном слоте и проверено
- Переключено на продакшн-среду
Дальнейшие действия
- Сопоставление API от встроенного процесса к изолированному рабочему — полный справочник по API для вашей миграции
- Обзор Устойчивые функции для изолированного рабочего .NET
- Версии Устойчивые функции и руководство по миграции
Связанный контент
- руководство по миграции официальное руководство Microsoft (все Функции Azure)
- .NET обзор изолированного рабочего процесса
- Различия между изолированными рабочими моделями
- Сериализация и сохраняемость в Устойчивые функции
- Развертывание без простоя для Устойчивые функции
- Настройка планировщика устойчивых задач