Observação
O acesso a essa página exige autorização. Você pode tentar entrar ou alterar diretórios.
O acesso a essa página exige autorização. Você pode tentar alterar os diretórios.
Este guia orienta você pela migração de seu aplicativo .NET Durable Functions do modelo em processo para o modelo de trabalho isolado. O modelo em processo chega ao fim do suporte em 10 de novembro de 2026. Após essa data, nenhuma atualização de segurança ou correções de bug são fornecidas. O modelo de trabalho isolado também oferece controle total do processo, injeção de dependência de .NET padrão e acesso aos recursos mais recentes da plataforma.
Aviso
O suporte para o modelo em processo termina em 10 de novembro de 2026. Recomendamos migrar agora. Para obter informações sobre o modelo de trabalho isolado, consulte .NET visão geral do processo de trabalho isolado.
Lista de verificação de migração
Use a seguinte lista de verificação para acompanhar seu progresso em cada etapa de migração:
| Passo | Seção |
|---|---|
| 1. Verificar pré-requisitos | Pré-requisitos |
| 2. Atualizar o arquivo de projeto | Atualizar o arquivo de projeto |
| 3. Adicionar Program.cs | Adicionar Program.cs |
| 4. Atualizar referências de pacote | Atualizar referências de pacote |
| 5. Atualizar código de função | Atualizar código de função |
| 6. Atualizar local.settings.json | Atualizar local.settings.json |
| 7. Testar localmente | Testar localmente |
| 8. Implantar no Azure | Implantar no Azure |
Pré-requisitos
- Azure Functions Core Tools v4.x ou posterior
- .NET SDK 8.0 (ou sua versão de .NET de destino)
- Visual Studio 2022 ou VS Code com extensão Azure Functions
Identificar aplicativos para migrar (opcional)
Se você não tiver certeza de quais aplicativos ainda usam o modelo em processo, execute este script Azure PowerShell:
$FunctionApps = Get-AzFunctionApp
$AppInfo = @{}
foreach ($App in $FunctionApps)
{
if ($App.Runtime -eq 'dotnet')
{
$AppInfo.Add($App.Name, $App.Runtime)
}
}
$AppInfo
Aplicativos que se apresentam dotnet como tempo de execução usam o modelo em processo. Os aplicativos que mostram dotnet-isolated já usam o modelo de trabalho isolado.
Atualizar o arquivo de projeto
Antes (em processamento)
<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>
Após (trabalhador isolado)
<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>
As principais alterações são alternar para um tipo de saída executável e substituir todos os pacotes Microsoft.Azure.WebJobs.* por seus equivalentes Microsoft.Azure.Functions.Worker.*.
Adicionar Program.cs
O modelo de trabalhador isolado requer um ponto de entrada Program.cs. Crie esse arquivo na raiz do projeto. Se você tiver uma classe \FunctionsStartup em \Startup.cs, mova os registros de serviço para o bloco \ConfigureServices e exclua \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();
Atualizar referências de pacote
mapeamento do pacote Durable Functions
| Pacote em processamento | Pacote de trabalhador isolado |
|---|---|
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 |
Mapeamento de pacotes de extensões comuns
| Em andamento | Trabalhador isolado |
|---|---|
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 |
Importante
Remova as referências a namespaces Microsoft.Azure.WebJobs.* e Microsoft.Azure.Functions.Extensions do seu projeto.
Atualizar código de função
Esta seção aborda as alterações de código para cada tipo de Durable Functions. Vá para a seção para os tipos de função que seu aplicativo usa:
- Alterações de namespace
- Funções de orquestrador
- Funções de atividade
- Funções de cliente
- Políticas de repetição (se usadas )
- Funções de entidade (se usadas)
Para obter um mapeamento completo de API por API, consulte a referência de API.
Alterações de 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;
Alterações no atributo de função
// Before (In-Process)
[FunctionName("MyOrchestrator")]
// After (Isolated Worker)
[Function(nameof(MyOrchestrator))]
Alterações na função do orquestrador
Antes (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 };
}
Depois (Trabalhador Isolado):
[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 };
}
Principais diferenças
| Aspecto | Em Processo | Trabalhador Isolado |
|---|---|---|
| Tipo de contexto | IDurableOrchestrationContext |
TaskOrchestrationContext |
| Logger | Parâmetro ILogger |
context.CreateReplaySafeLogger() |
| Attribute | [FunctionName] |
[Function] |
Alterações na função de atividade
Antes (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;
}
Depois (Trabalhador Isolado):
[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;
}
Modificações nas funções do cliente
Antes (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);
}
Depois (Trabalhador Isolado):
[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);
}
Alterações de tipo de cliente
| Em andamento | Trabalhador isolado |
|---|---|
IDurableOrchestrationClient |
DurableTaskClient |
StartNewAsync() |
ScheduleNewOrchestrationInstanceAsync() |
CreateCheckStatusResponse() |
CreateCheckStatusResponseAsync() |
HttpRequest / IActionResult |
HttpRequestData / HttpResponseData |
Política de Repetição de alteração
Usos em processo RetryOptions com CallActivityWithRetryAsync. O trabalhador isolado usa TaskOptions com o padrão CallActivityAsync.
Antes (In-Process):
var retryOptions = new RetryOptions(
firstRetryInterval: TimeSpan.FromSeconds(5),
maxNumberOfAttempts: 3);
string result = await context.CallActivityWithRetryAsync<string>(
"MyActivity", retryOptions, input);
Depois (Trabalhador Isolado):
var retryOptions = new TaskOptions(
new TaskRetryOptions(new RetryPolicy(
maxNumberOfAttempts: 3,
firstRetryInterval: TimeSpan.FromSeconds(5))));
string result = await context.CallActivityAsync<string>(
"MyActivity", input, retryOptions);
Alterações na função de entidade
Antes (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;
}
}
Depois (Trabalhador Isolado):
[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;
}
Mudanças de comportamento disruptivas
Examine essas alterações antes de testar seu aplicativo migrado. Para obter o mapeamento completo da API por API, consulte a referência de API.
Aviso
Padrão de serialização alterado: o trabalhador isolado usa System.Text.Json por padrão em vez de Newtonsoft.Json. Se suas orquestrações fizerem uso de objetos complexos, teste a serialização com cuidado. Confira as diferenças de serialização JSON para opções de configuração.
Aviso
Alteração padrão ContinueAsNew: o preserveUnprocessedEvents padrão do parâmetro foi alterado de false (2.x) para true (isolado). Se a sua orquestração utiliza ContinueAsNew e depende do descarte de eventos não processados, passe explicitamente as instruções necessárias preserveUnprocessedEvents: false.
Observação
Alteração padrão do RestartAsync: o padrão do parâmetro restartWithNewInstanceId foi alterado de true (2.x) para false (isolado). Se o código chamar RestartAsync e depender de uma nova ID de instância que está sendo gerada, passe o ID explicitamente restartWithNewInstanceId: true.
Outras alterações notáveis:
-
Proxies de entidade removidos –
CreateEntityProxy<T>não está disponível. UseEntities.CallEntityAsyncouEntities.SignalEntityAsyncdiretamente. -
Operações de hub entre tarefas removidas – sobrecargas que aceitavam
taskHubName/connectionNamenão estão disponíveis. Há suporte apenas para operações do mesmo hub de tarefas. -
Histórico de orquestração movido –
DurableOrchestrationStatus.Historynão está mais presente no objeto de status. UseDurableTaskClient.GetOrchestrationHistoryAsync.
Atualizar local.settings.json
A principal mudança é a configuração de FUNCTIONS_WORKER_RUNTIME de dotnet para dotnet-isolated.
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet-isolated"
}
}
Observação
Sua configuração de back-end de armazenamento (Armazenamento do Azure, MSSQL, Netherite ou Agendador de Tarefas Duráveis) não é alterada pela migração. Mantenha as configurações relacionadas ao armazenamento existentes.
Testar localmente
Execute seu aplicativo de funções localmente e verifique se todas as orquestrações, atividades e entidades funcionam corretamente.
func start
Verificar a funcionalidade
Teste os seguintes cenários conforme aplicável:
- Iniciar uma orquestração com um gatilho HTTP
- Monitorar o estado da orquestração
- Verificar a ordem de execução da atividade
- Testar operações de entidade, se aplicável
- Verificar a telemetria do Application Insights
Publicar no Azure
Recomenda-se o uso de slots de implantação
Use slots de implantação para minimizar o tempo de inatividade:
- Crie um intervalo de preparação para seu aplicativo de função.
-
Atualizar a configuração do intervalo de preparação:
- Defina
FUNCTIONS_WORKER_RUNTIMEcomodotnet-isolated. - Atualize a versão da pilha .NET, se necessário.
- Defina
- Implante o código migrado no intervalo de preparo.
- Teste minuciosamente no intervalo de preparo.
- Execute a troca de intervalos para mover as alterações para a produção.
Atualizar as definições da aplicação
No portal do Azure ou por meio da CLI:
az functionapp config appsettings set \
--name <FUNCTION_APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--settings FUNCTIONS_WORKER_RUNTIME=dotnet-isolated
Atualizar a configuração de stack
Se estiver almejando uma versão diferente do .NET:
az functionapp config set \
--name <FUNCTION_APP_NAME> \
--resource-group <RESOURCE_GROUP> \
--net-framework-version v8.0
Problemas comuns de migração
Problema: erros de carregamento da montagem
Sintoma:Could not load file or assembly Erros.
Solução: certifique-se de remover todas as referências de pacote Microsoft.Azure.WebJobs.* e substituí-las por equivalentes de trabalho isolados.
Problema: Atributo de associação não encontrado
Sintoma:The type or namespace 'QueueTrigger' could not be found
Solução: Adicione o pacote de extensão apropriado e atualize usando instruções:
// Add using statement
using Microsoft.Azure.Functions.Worker;
// Install package
// dotnet add package Microsoft.Azure.Functions.Worker.Extensions.Storage.Queues
Problema: IDurableOrchestrationContext não encontrado
Sintoma:The type or namespace 'IDurableOrchestrationContext' could not be found
Solução: Substitua por TaskOrchestrationContext:
using Microsoft.DurableTask;
[Function(nameof(MyOrchestrator))]
public static async Task MyOrchestrator([OrchestrationTrigger] TaskOrchestrationContext context)
{
// ...
}
Problema: diferenças de serialização JSON
Sintoma: Erros de serialização ou formatos de dados inesperados
Solução: O modelo isolado usa System.Text.Json por padrão. Configurar a serialização em Program.cs:
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.ConfigureServices(services => {
services.Configure<JsonSerializerOptions>(options => {
options.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
});
})
.Build();
Para usar Newtonsoft.Json em vez disso:
services.Configure<WorkerOptions>(options => {
options.Serializer = new NewtonsoftJsonObjectSerializer();
});
Problema: Migrando configurações de serialização personalizadas
Sintoma: Você usou IMessageSerializerSettingsFactory no modelo em processo e precisa do equivalente no trabalhador isolado.
Solução: Configurar o serializador de nível de trabalho em Program.cs. Para obter detalhes, consulte a seção alterações comportamentais da referência da API e Serialização e persistência no Durable Functions.
Para usar Newtonsoft.Json com configurações personalizadas:
// 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();
Observação
Essa abordagem requer os pacotes NuGet Newtonsoft.Json e Azure.Core.Serialization.
Lista de Verificação
Use esta lista de verificação para garantir uma migração completa:
- Arquivo de projeto atualizado com
<OutputType>Exe</OutputType> - Substituí
Microsoft.NET.Sdk.Functionspor pacotes de trabalhadores - Substituído
Microsoft.Azure.WebJobs.Extensions.DurableTaskpor pacote isolado - Criado
Program.cscom a configuração de host - Classe removida
FunctionsStartup(se presente) - Tudo foi atualizado
[FunctionName]para[Function] - Substituído
IDurableOrchestrationContextporTaskOrchestrationContext - Substituído
IDurableOrchestrationClientporDurableTaskClient - O registro de log foi atualizado para usar DI ou
FunctionContext - Atualizado
local.settings.jsoncomdotnet-isolatedtempo de execução - Removido todos os
Microsoft.Azure.WebJobs.*usando instruções - Adicionado
Microsoft.Azure.Functions.Workerusando declarações - Substituído por chamadas diretas
CreateEntityProxy<T>CallEntityAsync/SignalEntityAsync - Substituídas as sobrecargas de operação de hubs de tarefas cruzadas (se houver uso)
- Chamadas by-ID em lote
GetStatusAsync/PurgeInstanceHistoryAsyncsubstituídas por chamadas individuais ou baseadas em filtro - Acesso migrado
DurableOrchestrationStatus.HistoryparaGetOrchestrationHistoryAsync - Parâmetros de construtor de entidade
DispatchAsyncatualizados para usar DI - Testou todas as funções localmente
- Implantado no intervalo de testes e verificado
- Alternado para produção
Próximas Etapas
- Mapeamento de API de trabalhador isolado em processo – referência completa de API para sua migração
- Visão geral das Durable Functions para trabalhador isolado .NET
- Versões do Durable Functions e guia de migração
Conteúdo relacionado
- Guia oficial de migração da Microsoft (todas as Azure Functions)
- .NET visão geral do processo de trabalho isolado
- Diferenças no modelo de trabalho isolado
- Serialização e persistência em Durable Functions
- Implantação sem tempo de inatividade para Durable Functions
- Configurar o Agendador de Tarefas Duráveis