Partilhar via


Guia para executar C# Azure Functions no modelo de trabalhador isolado

Este artigo introduz o trabalho com Azure Functions em .NET usando o modelo de trabalhador isolado. Este modelo permite que o seu projeto aponte versões do .NET independentemente de outros componentes de tempo de execução. Para informações sobre versões específicas .NET suportadas, veja c0.

Use os seguintes links para começar a construir imediatamente funções do modelo de trabalhador isolado do .NET.

Introdução Conceitos Exemplos

Para saber como implementar um projeto de modelo de trabalhador isolado no Azure, veja Implementar nas Funcionalidades do Azure.

Benefícios do modelo de trabalhador isolado

Podes executar as funções da tua biblioteca de classes .NET em dois modos: ou no mesmo processo como o runtime host das Funções (em processo) ou num processo worker isolado. Quando as suas funções .NET funcionam num processo de trabalhador isolado, pode beneficiar dos seguintes benefícios:

  • Menos conflitos: como suas funções são executadas em um processo separado, os assemblies usados em seu aplicativo não entram em conflito com versões diferentes dos mesmos assemblies usados pelo processo de host.
  • Controle total do processo: você controla a inicialização do aplicativo, o que significa que você pode gerenciar as configurações usadas e o middleware iniciado.
  • Injeção padrão de dependências: Como tem controlo total do processo, pode usar os comportamentos atuais de .NET para injeção de dependências e incorporar middleware na sua aplicação de funções.
  • Flexibilidade de versão do .NET: Executar fora do processo anfitrião significa que as suas funcionalidades podem ser executadas em versões de .NET não suportadas nativamente pela plataforma Functions, incluindo o .NET Framework.

Se você tiver um aplicativo de função C# existente que seja executado em processo, precisará migrar seu aplicativo para aproveitar esses benefícios. Para mais informações, consulte Migrar apps .NET do modelo em-processo para o modelo de trabalhador isolado.

Para uma comparação abrangente entre os dois modos, veja Diferenças entre in-process e worker process isolado nas funções .NET do Azure.

Versões suportadas

As versões do runtime Functions suportam versões específicas do .NET. Para saber mais sobre as versões das Funções, consulte Azure Functions visão geral das versões em tempo de execução. O suporte à versão também depende se suas funções são executadas no processo ou no processo de trabalho isolado.

Nota

Para saber como alterar a versão de tempo de execução do Functions usada pelo seu aplicativo de função, consulte Exibir e atualizar a versão atual do tempo de execução.

A tabela seguinte mostra o nível mais elevado de .NET ou Framework .NET que pode ser usado com uma versão específica de Functions.

Versão do tempo de execução das Funções Modelo de trabalhador isolado Modelo em processamento4
Funções 4.x1 .NET 105
.NET 9.0
.NET 8.0
.NET Framework 4.82
.NET 8.0
Funções 1.x3 n/d .NET Framework 4.8

O 1 .NET 6 era anteriormente suportado em ambos os modelos, mas atingiu o fim do suporte oficial a 12 de novembro de 2024. O .NET 7 era anteriormente suportado no modelo de trabalhador isolado, mas atingiu o fim do apoio oficial a 14 de maio de 2024.

2 O processo de compilação também requer o SDK .NET.

3 O suporte termina para a versão 1.x da execução Azure Functions a 14 de setembro de 2026. Para mais informações, consulte este anúncio de suporte. Para obter suporte total contínuo, você deve migrar seus aplicativos para a versão 4.x.

4 O suporte para o modelo em processo termina em 10 de novembro de 2026. Para mais informações, consulte este anúncio de suporte. Para obter suporte total contínuo, você deve migrar seus aplicativos para o modelo de trabalho isolado.

5 Não é possível correr aplicações .NET 10 no Linux no plano de Consumo. Para rodar no Linux, você deve usar o plano Flex Consumption. Para instruções de migração passo a passo, consulte Migrar as aplicações do plano de Consumo para o plano Flex Consumption.

Para as últimas notícias sobre os lançamentos do Azure Functions, incluindo a remoção de versões menores antigas específicas, acompanhe os anúncios do Azure App Service.

Estrutura do Project

Um projeto .NET para Azure Functions que usa o modelo de trabalhador isolado é basicamente um projeto de consola em .NET que tem como alvo um runtime .NET suportado. Os ficheiros seguintes são os ficheiros básicos necessários em qualquer projeto isolado .NET:

  • Ficheiro de projeto C# (.csproj) que define o projeto e as dependências.
  • Program.cs arquivo que é o ponto de entrada para o aplicativo.
  • Todos os arquivos de código que definem suas funções.
  • O ficheiro host.json que define a configuração partilhada por funções no seu projeto.
  • local.settings.json é um ficheiro que define variáveis de ambiente usadas pelo seu projeto quando executado localmente na sua máquina.

Para exemplos completos, consulte o projeto de exemplo do .NET 8 e o projeto de exemplo do .NET Framework 4.8.

Referências de pacotes

Um projeto .NET para Azure Functions que utiliza o modelo de trabalhador isolado usa um conjunto único de pacotes, tanto para funcionalidades principais quanto para extensões de "binding".

Pacotes principais

Para executar as suas funções .NET num processo trabalhador isolado, precisa dos seguintes pacotes:

As versões mínimas destes pacotes dependem da sua versão .NET alvo:

Versão .NET Microsoft.Azure.Functions.Worker Microsoft.Azure.Functions.Worker.Sdk
.NET 10 2.50.0 ou posterior 2.0.5 ou posterior
.NET 9 2.0.0 ou posterior 2.0.0 ou posterior
.NET 8 1.16.0 ou posterior 1.11.0 ou posterior
Framework .NET 1.16.0 ou posterior 1.11.0 ou posterior

Versão 2.x

As versões 2.x dos pacotes principais alteram os frameworks suportados e trazem suporte para novas APIs .NET a partir destas versões posteriores. Ao atualizar para as versões 2.x, observe as seguintes alterações:

  • A partir da versão 2.0.0 da Microsoft. Azure. Functions.Worker.Sdk:
    • O SDK inclui configurações padrão para compilações de contêiner do SDK.
    • O SDK inclui suporte para dotnet run quando o Azure Functions Core Tools está instalado. No Windows, instala as Ferramentas Centrais através de um mecanismo diferente do NPM.
  • A partir da versão 2.0.0 da Microsoft. Azure. Functions.Worker:
    • Esta versão adiciona suporte para IHostApplicationBuilder. Alguns exemplos neste guia incluem separadores para mostrar alternativas usando IHostApplicationBuilder. Estes exemplos requerem as versões 2.x.
    • A validação do escopo do provedor de serviços é incluída por padrão se executada em um ambiente de desenvolvimento. Este comportamento corresponde ao ASP.NET Core.
    • A EnableUserCodeException opção está ativada por padrão. A propriedade está agora marcada como obsoleta.
    • A IncludeEmptyEntriesInMessagePayload opção está ativada por padrão. Com esta opção ativada, as cargas úteis do gatilho que representam coleções incluem sempre entradas vazias. Por exemplo, se uma mensagem for enviada sem corpo, uma entrada vazia ainda está presente em string[] nos dados de disparo. A inclusão de entradas vazias facilita o cruzamento com matrizes de metadados que a função também pode referenciar. Você pode desabilitar esse comportamento definindo IncludeEmptyEntriesInMessagePayload como false na configuração do WorkerOptions serviço.
    • A ILoggerExtensions classe é renomeada para FunctionsLoggerExtensions. A renomeação evita um erro de chamada ambígua ao usar LogMetric() numa instância de ILogger.
    • Para aplicações que usam HttpResponseData, o WriteAsJsonAsync() método já não define o código de estado para 200 OK. Na 1.x, este comportamento sobrepunha outros códigos de erro que definiste.
  • As versões 2.x eliminam o suporte ao .NET 5 TFM.

Pacotes de extensão

Como as funções de processos de trabalho isolados em .NET usam diferentes tipos de bindings, requerem um conjunto único de pacotes de extensões de bindings.

Encontra estes pacotes de extensões em Microsoft. Azure. Functions.Worker.Extensions.

Arranque e configuração

Quando usas o modelo de trabalhador isolado, tens acesso ao início da tua aplicação de funções, que normalmente está em Program.cs. Você é responsável por criar e iniciar sua própria instância de host. Assim, também tem acesso direto ao pipeline de configuração da sua aplicação. Com o processo trabalhador isolado do .NET Functions, pode adicionar configurações muito mais facilmente, injetar dependências e executar o seu próprio middleware.

Para usar IHostApplicationBuilder, a sua aplicação deve usar a versão 2.x ou posterior dos pacotes principais.

O código a seguir mostra um exemplo de um pipeline IHostApplicationBuilder:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = FunctionsApplication.CreateBuilder(args);

builder.Services
    .AddApplicationInsightsTelemetryWorkerService()
    .ConfigureFunctionsApplicationInsights();

builder.Logging.Services.Configure<LoggerFilterOptions>(options =>
    {
        // The Application Insights SDK adds a default logging filter that instructs ILogger to capture only Warning and more severe logs. Application Insights requires an explicit override.
        // Log levels can also be configured using appsettings.json. For more information, see https://learn.microsoft.com/azure/azure-monitor/app/worker-service#ilogger-logs
        LoggerFilterRule? defaultRule = options.Rules.FirstOrDefault(rule => rule.ProviderName
            == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");
        if (defaultRule is not null)
        {
            options.Rules.Remove(defaultRule);
        }
    });

var host = builder.Build();

Antes de chamar Build() no IHostApplicationBuilder, deverá:

  • Se pretender utilizar a integração do ASP.NET Core, chame builder.ConfigureFunctionsWebApplication().
  • Se você estiver escrevendo seu aplicativo usando F#, talvez seja necessário registrar algumas extensões de vinculação. Consulte a documentação de configuração da extensão Blobs, da extensão Tables e da extensão Cosmos DB quando planeia usar estas extensões numa aplicação F#.
  • Configure qualquer serviço ou configuração de aplicativo que o seu projeto exija. Consulte Configuração para obter detalhes.
  • Se planeia usar o Application Insights, deve chamar AddApplicationInsightsTelemetryWorkerService() e ConfigureFunctionsApplicationInsights() na propriedade Services do builder. Consulte Application Insights para obter detalhes.

Se o seu projeto tem como alvo o .NET Framework 4.8, também precisa adicionar FunctionsDebugger.Enable(); antes de criar o HostBuilder. Deve ser a primeira linha do seu Main() método. Para mais informações, consulte Depuração ao ter como alvo o .NET Framework.

O IHostApplicationBuilder é usado para criar e retornar uma instância totalmente inicializada IHost , que você executa de forma assíncrona para iniciar seu aplicativo de função.

await host.RunAsync();

Configuração

O tipo de construtor que usa determina como configura a aplicação.

Use o FunctionsApplication.CreateBuilder() método para adicionar as definições necessárias para a aplicação funcional funcionar. O método inclui a seguinte funcionalidade:

  • Conjunto padrão de conversores.
  • Defina o padrão JsonSerializerOptions para ignorar a capitalização em nomes de propriedade.
  • Integra com o registo do Azure Functions.
  • Middleware e funcionalidades de vinculação de saída.
  • Middleware de execução de funções.
  • Suporte padrão para gRPC.
  • Aplique outros padrões de Host.CreateDefaultBuilder().

Tens acesso ao pipeline do builder, por isso podes definir quaisquer configurações específicas da aplicação durante a inicialização. Você pode chamar métodos de extensão na propriedade Configuration do construtor para adicionar quaisquer fontes de configuração exigidas pelo seu código. Para mais informações sobre app configuration, consulte Configuration em ASP.NET Core.

Estas configurações aplicam-se apenas ao código de trabalhador que escreves. Eles não influenciam diretamente a configuração do anfitrião das Funções, nem os gatilhos e associações. Para fazer alterações ao host de funções ou à configuração de disparador e ligação, use o ficheiro host.json.

Nota

Fontes de configuração personalizadas não podem ser usadas para a configuração de triggers e bindings. A configuração de acionamento e vinculação deve estar disponível para a plataforma Functions, e não apenas para o código do aplicativo. Pode fornecer esta configuração através das definições da aplicação, Key Vault references ou App Configuration references.

Injeção de dependência

O modelo de trabalhador isolado utiliza mecanismos .NET padrão para injetar serviços.

Quando utilizar um IHostApplicationBuilder, use a sua propriedade Services para aceder à IServiceCollection. O exemplo a seguir injeta uma dependência de serviço singleton:

builder.Services.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();

Este código requer using Microsoft.Extensions.DependencyInjection;. Para saber mais, consulte Injeção de dependência em ASP.NET Core.

Registar clientes Azure

Use injeção de dependência para interagir com outros serviços do Azure. Podes injetar clientes a partir do SDK Azure para .NET usando o Microsoft.Extensions.Azure pacote. Após instalar o pacote, regista os clientes chamando AddAzureClients() na coleção de serviços em Program.cs. O exemplo seguinte configura um cliente nomeado para Azure Blobs:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.Azure;
using Microsoft.Extensions.Hosting;

var builder = FunctionsApplication.CreateBuilder(args);

builder.Services
    .AddAzureClients(clientBuilder =>
        {
            clientBuilder.AddBlobServiceClient(builder.Configuration.GetSection("MyStorageConnection"))
                .WithName("copierOutputBlob");
        });

builder.Build().Run();

O exemplo seguinte mostra como pode usar estes tipos de registo e SDK para copiar o conteúdo do blob como um fluxo de um contentor para outro, usando um cliente injetado:

using Microsoft.Extensions.Azure;
using Microsoft.Extensions.Logging;

namespace MyFunctionApp
{
    public class BlobCopier
    {
        private readonly ILogger<BlobCopier> _logger;
        private readonly BlobContainerClient _copyContainerClient;

        public BlobCopier(ILogger<BlobCopier> logger, IAzureClientFactory<BlobServiceClient> blobClientFactory)
        {
            _logger = logger;
            _copyContainerClient = blobClientFactory.CreateClient("copierOutputBlob").GetBlobContainerClient("samples-workitems-copy");
            _copyContainerClient.CreateIfNotExists();
        }

        [Function("BlobCopier")]
        public async Task Run([BlobTrigger("samples-workitems/{name}", Connection = "MyStorageConnection")] Stream myBlob, string name)
        {
            await _copyContainerClient.UploadBlobAsync(name, myBlob);
            _logger.LogInformation($"Blob {name} copied!");
        }

    }
}

O ILogger<T> neste exemplo também é obtido através de injeção de dependência, por isso é registado automaticamente. Para saber mais sobre as opções de configuração para registo de logs, consulte Logging.

Gorjeta

O exemplo usa uma cadeia literal para o nome do cliente tanto em Program.cs como na função. Em vez disso, considere usar uma cadeia constante partilhada definida na classe de funções. Por exemplo, você pode adicionar public const string CopyStorageClientName = nameof(_copyContainerClient); e, em seguida, fazer referência BlobCopier.CopyStorageClientName em ambos os locais. Da mesma forma, você pode definir o nome da seção de configuração com a função em vez de em Program.cs.

Middleware

O modelo de trabalhador isolado também suporta o registo de middleware, novamente usando um modelo semelhante ao que existe no ASP.NET. Este modelo oferece a capacidade de injetar lógica no pipeline de invocação, e antes e depois de as funções serem executadas.

O método de extensão ConfigureFunctionsWorkerDefaults tem uma sobrecarga que permite registar o seu próprio middleware, como vê no exemplo seguinte.

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = FunctionsApplication.CreateBuilder(args);

// Register our custom middlewares with the worker
builder
    .UseMiddleware<ExceptionHandlingMiddleware>()
    .UseMiddleware<MyCustomMiddleware>()
    .UseWhen<StampHttpHeaderMiddleware>((context) =>
    {
        // We want to use this middleware only for http trigger invocations.
        return context.FunctionDefinition.InputBindings.Values
                        .First(a => a.Type.EndsWith("Trigger")).Type == "httpTrigger";
    });

builder.Build().Run();

O UseWhen método de extensão regista um middleware que é executado condicionalmente. Deve passar um predicado que retorne um valor booleano a este método. O middleware participa no pipeline de processamento de invocações quando o predicado retorna true.

Os seguintes métodos de extensão em FunctionContext facilitam o trabalho com middleware no modelo isolado.

Método Descrição
GetHttpRequestDataAsync Obtém a instância HttpRequestData quando acionada por um gatilho HTTP. Esse método retorna uma instância de ValueTask<HttpRequestData?>, que é útil quando deseja ler dados da mensagem, como cabeçalhos de solicitação e cookies.
GetHttpResponseData Obtém a instância HttpResponseData quando invocada por um trigger HTTP.
GetInvocationResult Obtém uma instância de InvocationResult, que representa o resultado da execução da função atual. Use a Value propriedade para obter ou definir o valor conforme necessário.
GetOutputBindings Obtém as entradas de vinculação de saída para a execução da função atual. Cada entrada no resultado deste método é do tipo OutputBindingData. Você pode usar a Value propriedade para obter ou definir o valor conforme necessário.
BindInputAsync Vincula um item de vinculação de entrada para a instância solicitada BindingMetadata . Por exemplo, usa este método quando tiveres uma função com uma BlobInput ligação de entrada que precisa de ser usada pelo teu middleware.

Este exemplo mostra uma implementação de middleware que lê a HttpRequestData instância e atualiza a HttpResponseData instância durante a execução da função:

internal sealed class StampHttpHeaderMiddleware : IFunctionsWorkerMiddleware
{
    public async Task Invoke(FunctionContext context, FunctionExecutionDelegate next)
    {
        var requestData = await context.GetHttpRequestDataAsync();

        string correlationId;
        if (requestData!.Headers.TryGetValues("x-correlationId", out var values))
        {
            correlationId = values.First();
        }
        else
        {
            correlationId = Guid.NewGuid().ToString();
        }

        await next(context);

        context.GetHttpResponseData()?.Headers.Add("x-correlationId", correlationId);
    }
}

Este middleware verifica a presença de um cabeçalho de pedido específico (x-correlationId). Quando o cabeçalho está presente, o middleware usa o valor do cabeçalho para carimbar um cabeçalho de resposta. Caso contrário, gera um novo valor GUID e usa esse valor para carimbar o cabeçalho da resposta.

Gorjeta

O padrão mostrado anteriormente de definir cabeçalhos de resposta depois await next(context) pode não funcionar de forma fiável em todos os cenários. Este problema é particularmente verdadeiro ao usar integração com ASP.NET Core ou em certas configurações de tempo de execução onde o fluxo de resposta pode já ter sido enviado. Para garantir que os cabeçalhos estão corretamente definidos, considere recuperar a resposta de context.GetInvocationResult().Value e assegurar que os cabeçalhos estão definidos antes que a resposta seja devolvida pela sua função, em vez de tentar modificá-los no middleware depois da execução da função estar completa.

Para um exemplo mais completo de utilização de middleware personalizado na sua aplicação de funcionalidades, veja a amostra de referência de middleware personalizado .

Personalizando a serialização JSON

O modelo de trabalhador isolado usa System.Text.Json por padrão. Você pode personalizar o comportamento do serializador configurando serviços como parte do seu Program.cs arquivo. Esta secção cobre a serialização de uso geral e não influencia a serialização JSON de gatilho HTTP com integração ASP.NET Core, que deve configurar separadamente.

using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = FunctionsApplication.CreateBuilder(args);

builder.ConfigureFunctionsWebApplication();

builder.Services.Configure<JsonSerializerOptions>(jsonSerializerOptions =>
    {
        jsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
        jsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
        jsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;

        // override the default value
        jsonSerializerOptions.PropertyNameCaseInsensitive = false;
    });

builder.Build().Run();

Para usar JSON.NET (Newtonsoft.Json) para serialização, instale o pacote Microsoft.Azure.Core.NewtonsoftJson. Depois, no seu registo de serviço, reatribua a propriedade Serializer sobre a configuração WorkerOptions. O exemplo seguinte mostra esta configuração usando ConfigureFunctionsWebApplication, mas também funciona para ConfigureFunctionsWorkerDefaults:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = FunctionsApplication.CreateBuilder(args);

builder.ConfigureFunctionsWebApplication();

builder.Services.Configure<WorkerOptions>(workerOptions =>
    {
        var settings = NewtonsoftJsonObjectSerializer.CreateJsonSerializerSettings();
        settings.ContractResolver = new CamelCasePropertyNamesContractResolver();
        settings.NullValueHandling = NullValueHandling.Ignore;

        workerOptions.Serializer = new NewtonsoftJsonObjectSerializer(settings);
    });

builder.Build().Run();

Métodos reconhecidos como funções

Um método de função é um método público de uma classe pública com um Function atributo aplicado ao método e um atributo trigger aplicado a um parâmetro de entrada, conforme mostrado no exemplo a seguir:

[Function(nameof(QueueInputOutputFunction))]
[QueueOutput("output-queue")]
public string[] QueueInputOutputFunction([QueueTrigger("input-queue")] Album myQueueItem, FunctionContext context)

O atributo trigger especifica o tipo de gatilho e vincula os dados de entrada a um parâmetro de método. A função de exemplo anterior é ativada por uma mensagem de fila, e a mensagem de fila é passada para o método no myQueueItem parâmetro.

O Function atributo marca o método como um ponto de entrada de função. O nome deve ser único dentro de um project, começar com uma letra e conter apenas letras, números, _ e -, com até 127 caracteres de extensão. Project templates frequentemente criam um método chamado Run, mas o nome do método pode ser qualquer nome válido de método C#. O método deve ser um membro público de uma classe pública. Geralmente, deve ser um método de instância para que os serviços possam ser transmitidos por meio de injeção de dependência.

Parâmetros de função

Aqui estão alguns dos parâmetros que você pode incluir como parte de uma assinatura de método de função:

  • Ligações, que são marcadas como tal, decorando os parâmetros como atributos. A função deve conter exatamente um parâmetro de gatilho.
  • Um objeto de contexto de execução, que fornece informações sobre a invocação atual.
  • Um token de cancelamento, usado para desligamento suave.

Contexto de execução

No modelo de trabalhador isolado, o processo trabalhador passa um objeto FunctionContext para os seus métodos de função. Este objeto permite-lhe obter uma instância ILogger para escrever nos logs chamando o método GetLogger e fornecendo uma cadeia categoryName. Você pode usar esse contexto para obter um ILogger sem ter que usar a injeção de dependência. Para obter mais informações, consulte Logging.

Tokens de cancelamento

Uma função pode aceitar um parâmetro cancellationToken , que permite que o sistema operacional notifique seu código quando a função estiver prestes a ser encerrada. Você pode usar essa notificação para garantir que a função não seja encerrada inesperadamente de uma forma que deixe os dados em um estado inconsistente.

As funções .NET que correm num processo trabalhador isolado suportam tokens de cancelamento. O exemplo a seguir gera uma exceção quando uma solicitação de cancelamento é recebida:

[Function(nameof(ThrowOnCancellation))]
public async Task ThrowOnCancellation(
    [EventHubTrigger("sample-workitem-1", Connection = "EventHubConnection")] string[] messages,
    FunctionContext context,
    CancellationToken cancellationToken)
{
    _logger.LogInformation("C# EventHub {functionName} trigger function processing a request.", nameof(ThrowOnCancellation));

    foreach (var message in messages)
    {
        cancellationToken.ThrowIfCancellationRequested();
        await Task.Delay(6000); // task delay to simulate message processing
        _logger.LogInformation("Message '{msg}' was processed.", message);
    }
}

O exemplo a seguir executa ações de limpeza quando uma solicitação de cancelamento é recebida:

[Function(nameof(HandleCancellationCleanup))]
public async Task HandleCancellationCleanup(
    [EventHubTrigger("sample-workitem-2", Connection = "EventHubConnection")] string[] messages,
    FunctionContext context,
    CancellationToken cancellationToken)
{
    _logger.LogInformation("C# EventHub {functionName} trigger function processing a request.", nameof(HandleCancellationCleanup));

    foreach (var message in messages)
    {
        if (cancellationToken.IsCancellationRequested)
        {
            _logger.LogInformation("A cancellation token was received, taking precautionary actions.");
            // Take precautions like noting how far along you are with processing the batch
            _logger.LogInformation("Precautionary activities complete.");
            break;
        }

        await Task.Delay(6000); // task delay to simulate message processing
        _logger.LogInformation("Message '{msg}' was processed.", message);
    }
}

Cenários que levam ao cancelamento

O token de cancelamento é sinalizado quando a invocação da função é cancelada. Várias razões podem levar ao cancelamento, e essas razões variam consoante o tipo de gatilho utilizado. Algumas razões comuns são:

  • Desconexão do cliente: O cliente que está a invocar a sua função desliga-se. Esta razão deve-se provavelmente a funções de gatilho HTTP.
  • Reinício da aplicação de funções: Você ou a plataforma reiniciam (ou param) a aplicação de funções aproximadamente na mesma altura em que uma invocação é solicitada. Uma reinicialização pode ocorrer devido a movimentos de instância de trabalho, atualizações de instância de trabalho ou dimensionamento.

Considerações de cancelamento

  • Invocações em voo durante um evento de reinício podem ser tentadas novamente dependendo de como foram ativadas. Para mais informações, consulte a documentação de repetição.

  • O host envia a invocação para o worker mesmo que o token de cancelamento seja cancelado antes de o host conseguir enviar o pedido de invocação ao worker.

  • Se não quiseres que as invocações pré-canceladas sejam enviadas ao trabalhador, adiciona a SendCanceledInvocationsToWorker propriedade ao teu host.json ficheiro para desativar este comportamento.

    Este exemplo mostra um host.json ficheiro que utiliza esta propriedade:

    {
        "version": "2.0",
        "SendCanceledInvocationsToWorker": "false"
    }
    
  • Definir SendCanceledInvocationsToWorker para false pode levar a uma FunctionInvocationCanceled exceção com o seguinte log:

    Foi solicitado o cancelamento. O pedido de invocação com id '{invocationId}' é cancelado e não será enviado ao trabalhador.

    Esta exceção ocorre quando o token de cancelamento é cancelado (como resultado de um dos eventos descritos anteriormente) antes do host enviar um pedido de invocação ao trabalhador. Esta exceção pode ser ignorada em segurança e é esperada quando SendCanceledInvocationsToWorker é false.

Programação assíncrona

O trabalhador .NET isolado não define um SynchronizationContext personalizado. Isto significa que SynchronizationContext.Current é null durante a execução da função. Após um await, as continuações são agendadas no pool de threads, que é o comportamento padrão .NET.

Como não há SynchronizationContext a suprimir, usar ConfigureAwait(false) no seu código de função não tem efeito prático. O processo trabalhador isolado corre como um host genérico padrão .NET (aplicação de consola), por isso o mesmo comportamento de async/await que se esperaria em qualquer ASP.NET Core ou aplicação de consola aplica-se aqui. Isto também é verdade para aplicações isoladas do .NET Framework (net48), uma vez que o processo trabalhador é sempre um executável de consola usando HostBuilder.

Nota

Os orquestradores Durable Functions têm as suas próprias restrições de threading. O thread de replay do orchestrator tem de executar continuações, pelo que a utilização de ConfigureAwait(false) em funções de orquestração ou middleware do orchestrator pode interferir na execução da orquestração. Para mais informações, consulte as restrições de código Durable Functions.

Enlaces

Defina ligações usando atributos em métodos, parâmetros e tipos de retorno. As associações podem fornecer dados como cadeias de caracteres, matrizes e tipos serializáveis, como objetos de classe antigos simples (POCOs). Para algumas extensões de vinculação, você também pode vincular a tipos específicos de serviço definidos em SDKs de serviço.

Para gatilhos HTTP, consulte a seção Gatilho HTTP.

Para um conjunto completo de amostras de referência que utilizam gatilhos e ligações com funções de processo de trabalho isolado, consulte a amostra de referência de extensões de ligação .

Ligações de entrada

Uma função pode ter zero ou mais ligações de entrada que passam dados para a função. Tal como nos triggers, defines ligações de entrada aplicando um atributo de ligação a um parâmetro de entrada. Quando a função é executada, o ambiente de execução tenta obter dados especificados na ligação. Os dados solicitados dependem frequentemente da informação fornecida pelo gatilho através dos parâmetros de ligação.

Ligações de saída

Para escrever numa ligação de saída, deve aplicar um atributo de ligação de saída ao método da função. Este atributo define como escrever no serviço vinculado. O valor de retorno do método é escrito na ligação de saída. Por exemplo, o exemplo a seguir grava um valor de cadeia de caracteres em uma fila de mensagens nomeada output-queue usando uma associação de saída:

[Function(nameof(QueueInputOutputFunction))]
[QueueOutput("output-queue")]
public string[] QueueInputOutputFunction([QueueTrigger("input-queue")] Album myQueueItem, FunctionContext context)
{
    // Use a string array to return more than one message.
    string[] messages = {
        $"Album name = {myQueueItem.Name}",
        $"Album songs = {myQueueItem.Songs}"};

    _logger.LogInformation("{msg1},{msg2}", messages[0], messages[1]);

    // Queue Output messages
    return messages;
}

Múltiplas associações de saída

Os dados gravados em uma ligação de saída são sempre o valor de retorno da função. Se você precisar gravar em mais de uma ligação de saída, deverá criar um tipo de retorno personalizado. Esse tipo de retorno deve ter o atributo de vinculação de saída aplicado a uma ou mais propriedades da classe. O exemplo seguinte é uma função acionada por HTTP que utiliza a integração com o ASP.NET Core e escreve tanto na resposta HTTP como numa vinculação de saída para a fila:

public class MultipleOutputBindings
{
    private readonly ILogger<MultipleOutputBindings> _logger;

    public MultipleOutputBindings(ILogger<MultipleOutputBindings> logger)
    {
        _logger = logger;
    }

    [Function("MultipleOutputBindings")]
    public MyOutputType Run([HttpTrigger(AuthorizationLevel.Function, "post")] HttpRequest req)
    {
        _logger.LogInformation("C# HTTP trigger function processed a request.");
        var myObject = new MyOutputType
        {
            Result = new OkObjectResult("C# HTTP trigger function processed a request."),
            MessageText = "some output"
        };
        return myObject;
    }

    public class MyOutputType
    {
        [HttpResult]
        public IActionResult Result { get; set; }

        [QueueOutput("myQueue")]
        public string MessageText { get; set; }
    }
}

Quando usa tipos de retorno personalizados para múltiplas ligações de saída com integração ASP.NET Core, deve adicionar o atributo [HttpResult] à propriedade que fornece o resultado. O atributo HttpResult está disponível ao usar SDK 1.17.3-preview2 ou posterior juntamente com versão 3.2.0 ou posterior da extensão HTTP e versão 1.3.0 ou posterior da extensão ASP.NET Core.

Tipos de SDK

Para alguns tipos de ligação específicas do serviço, pode fornecer dados de ligação utilizando tipos de SDKs e frameworks de serviço. Estes tipos oferecem capacidades além do que uma cadeia serializada ou um simples objeto CLR (POCO) pode proporcionar. Para usar os tipos mais recentes, atualize o seu project para usar versões mais recentes das dependências principais.

Dependência Requisito de versão
Microsoft. Azure. Functions.Worker 1.18.0 ou posterior
Microsoft. Azure. Functions.Worker.Sdk 1.13.0 ou posterior

Ao testar os tipos de SDK localmente na sua máquina, também precisa de usar Azure Functions Core Tools, versão 4.0.5000 ou posterior. Podes verificar a tua versão atual usando o func --version comando.

Cada extensão de ligação tem também o seu próprio requisito mínimo de versão, descrito nos artigos de referência da extensão. Estas extensões de binding suportam atualmente tipos de SDK:

Extension Types Nível de suporte
Azure Blob Storage BlobClient
BlobContainerClient
BlockBlobClient
PageBlobClient
AppendBlobClient
Gatilho: GA
Entrada: GA
Azure Cosmos DB CosmosClient
Database
Container
Entrada: GA
Azure Event Grid CloudEvent
EventGridEvent
Gatilho: GA
Azure Event Hubs EventData
EventHubProducerClient
Gatilho: GA
Azure Queue Storage QueueClient
QueueMessage
Gatilho: GA
Azure Service Bus ServiceBusClient
ServiceBusReceiver
ServiceBusSender
ServiceBusMessage
Gatilho: GA
Armazenamento de Tabela do Azure TableClient
TableEntity
Entrada: GA

Considerações para os tipos de SDK:

  • Ao usar expressões de associação que dependem de dados de gatilho, os tipos de SDK para o gatilho em si não podem ser usados.
  • Para cenários de saída onde podes usar um tipo de SDK, cria e trabalha diretamente com clientes SDK em vez de usar uma ligação de saída.
  • O gatilho Azure Cosmos DB utiliza o feed de alterações Azure Cosmos DB e expõe os elementos de alteração como tipos serializáveis em JSON. Como resultado, os tipos de SDK não são suportados para este trigger.

Acionador HTTP

Os gatilhos HTTP permitem que uma função seja invocada por uma solicitação HTTP. Pode usar duas abordagens diferentes:

  • Um modelo de integração ASP.NET Core que utiliza conceitos familiares aos programadores ASP.NET Core
  • Um modelo interno, que não requer dependências extras e usa tipos personalizados para solicitações e respostas HTTP. Esta abordagem é mantida para garantir a compatibilidade retroativa com aplicações .NET de trabalhadores isolados anteriores.

Integração ASP.NET Core

Esta secção mostra como trabalhar com os objetos HTTP de pedido e resposta subjacentes usando tipos de ASP.NET Core, incluindo HttpRequest, HttpResponse e IActionResult. Este modelo não está disponível para apps direcionadas ao .NET Framework, que devem usar o modelo interno.

Nota

Este modelo não expõe todas as funcionalidades do ASP.NET Core. Especificamente, não fornece acesso ao pipeline middleware ASP.NET Core nem às capacidades de roteamento. A integração do ASP.NET Core exige que uses pacotes atualizados.

Para permitir a integração do ASP.NET Core para HTTP:

  1. Adicione uma referência no seu projeto para o pacote Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore, versão 1.0.0 ou posterior.

  2. Atualize o seu project para usar estas versões específicas do pacote:

  3. No seu arquivo Program.cs, atualize a configuração do construtor de hosts para que chame ConfigureFunctionsWebApplication(). Este método substitui ConfigureFunctionsWorkerDefaults() se usarias esse método de outra forma. O exemplo a seguir mostra uma configuração mínima sem outras personalizações:

    Nota

    A sua aplicação deve referenciar a versão 2.0.0 ou posterior da Microsoft. Azure. Functions.Worker.Extensions.Http.AspNetCore para usar ASP.NET Core integração com IHostApplicationBuilder.

    using Microsoft.Azure.Functions.Worker.Builder;
    using Microsoft.Extensions.Hosting;
    
    var builder = FunctionsApplication.CreateBuilder(args);
    
    builder.ConfigureFunctionsWebApplication();    
    
    builder.Build().Run();
    
  4. Atualize quaisquer funções ativadas por HTTP para utilizar os tipos ASP.NET Core. Este exemplo mostra o padrão HttpRequest e um IActionResult usado para uma função simples "olá, mundo":

    [Function("HttpFunction")]
    public IActionResult Run(
        [HttpTrigger(AuthorizationLevel.Anonymous, "get")] HttpRequest req)
    {
        return new OkObjectResult($"Welcome to Azure Functions, {req.Query["name"]}!");
    }
    

Serialização JSON com integração ASP.NET Core

ASP.NET Core tem a sua própria camada de serialização e não é afetada por personalização da configuração geral de serialização. Para personalizar o comportamento de serialização usado para seus gatilhos HTTP, você precisa incluir uma .AddMvc() chamada como parte do registro do serviço. O IMvcBuilder devolvido pode ser usado para modificar as definições de serialização JSON da ASP.NET Core.

Podes continuar a usar HttpRequestData e HttpResponseData enquanto usas a integração ASP.NET, embora para a maioria das aplicações seja melhor usar HttpRequest e IActionResult. Usar HttpRequestData/HttpResponseData não invoca a camada de serialização ASP.NET Core e, em vez disso, depende da configuração general worker serialization para a aplicação. No entanto, quando a integração com ASP.NET Core está ativada, pode ainda ser necessário adicionar configuração. O comportamento padrão do ASP.NET Core é desautorizar a entrada síncrona. Para usar um serializador personalizado que não suporta E/S assíncrona, como NewtonsoftJsonObjectSerializer, precisa ativar E/S síncrona para a sua aplicação configurando o arquivo KestrelServerOptions.

O exemplo seguinte mostra como configurar JSON.NET (Newtonsoft.Json) e o pacote Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet para serialização usando esta abordagem:

using Microsoft.AspNetCore.Server.Kestrel.Core;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

var builder = FunctionsApplication.CreateBuilder(args);

builder.ConfigureFunctionsWebApplication();

builder.Services
    .AddApplicationInsightsTelemetryWorkerService()
    .ConfigureFunctionsApplicationInsights();

builder.Services.AddMvc().AddNewtonsoftJson();

// Only needed if using HttpRequestData/HttpResponseData and a serializer that doesn't support asynchronous IO
// builder.Services.Configure<KestrelServerOptions>(options => options.AllowSynchronousIO = true);

builder.Build().Run();

Modelo HTTP integrado

No modelo incorporado, o sistema converte a mensagem de pedido HTTP recebida num objeto HttpRequestData que passa para a função. Este objeto fornece dados da solicitação, incluindo Headers, , , CookieseIdentities, opcionalmente, uma mensagem URLBody. Este objeto representa o pedido HTTP mas não está diretamente ligado ao ouvinte HTTP subjacente nem à mensagem recebida.

Importante

Se usares HttpRequestData, o corpo do pedido HTTP não pode ser um fluxo. Por exemplo, se o pedido tiver o Transfer-Encoding: chunked cabeçalho e nenhum Content-Length cabeçalho, a HttpRequestData propriedade do Body objeto será um fluxo nulo. Se precisares de trabalhar com pedidos HTTP em streaming, considera usar o modelo de integração ASP.NET Core em vez disso.

Da mesma forma, a função devolve um objeto HttpResponseData, que fornece dados usados para criar a resposta HTTP, incluindo mensagens StatusCode, Headers e, opcionalmente, uma mensagem Body.

O exemplo a seguir demonstra o uso de HttpRequestData e HttpResponseData:

[Function(nameof(HttpFunction))]
public static HttpResponseData Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequestData req,
    FunctionContext executionContext)
{
    var logger = executionContext.GetLogger(nameof(HttpFunction));
    logger.LogInformation("message logged");

    var response = req.CreateResponse(HttpStatusCode.OK);
    response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
    response.WriteString("Welcome to .NET isolated worker !!");

    return response;
}

Registo

Você pode gravar em logs usando ILogger<T> ou ILogger instância. Pode obter o logger através da injeção de dependência de um ILogger<T> ou de um ILoggerFactory:

public class MyFunction {
    
    private readonly ILogger<MyFunction> _logger;
    
    public MyFunction(ILogger<MyFunction> logger) {
        _logger = logger;
    }
    
    [Function(nameof(MyFunction))]
    public void Run([BlobTrigger("samples-workitems/{name}", Connection = "")] string myBlob, string name)
    {
        _logger.LogInformation($"C# Blob trigger function Processed blob\n Name: {name} \n Data: {myBlob}");
    }

}

Nota

Quando injeta um ILogger<T> no construtor da sua classe, como no exemplo anterior, a categoria de log é automaticamente definida para o nome completamente qualificado dessa classe, como MyFunctionApp.MyFunction. Estes nomes de categorias contêm . caracteres (de época). Quando alojas a tua aplicação de funções no Linux, não podes usar variáveis de ambiente para sobrescrever níveis de registo em categorias que contêm pontos. Para contornar esta limitação, pode, em vez disso, configurar níveis de log no seu código ou num appsettings.json ficheiro.

Também poderás obter o registador de um objeto FunctionContext passado para a tua função. Chame o método GetLogger<T> ou GetLogger, passando um valor de cadeia que é o nome da categoria onde os registos estão escritos. A categoria é geralmente o nome da função específica a partir da qual os logs são gravados. Para mais informações sobre categorias, consulte o artigo de monitorização.

Use os métodos de ILogger<T> e ILogger para gravar vários níveis de log, como LogWarning ou LogError. Para mais informações sobre os níveis de registo, consulte o artigo de monitorização. Você pode personalizar os níveis de log para componentes adicionados ao seu código registrando filtros:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

var builder = FunctionsApplication.CreateBuilder(args);

builder.ConfigureFunctionsWebApplication();

// Registers IHttpClientFactory.
// By default this sends a lot of Information-level logs.
builder.Services.AddHttpClient();

// Disable IHttpClientFactory Informational logs.
// Note -- you can also remove the handler that does the logging: https://github.com/aspnet/HttpClientFactory/issues/196#issuecomment-432755765 
builder.Logging.AddFilter("System.Net.Http.HttpClient", LogLevel.Warning);
    
builder.Build().Run();

Como parte da configuração do seu aplicativo no Program.cs, você também pode definir o comportamento de como os erros são exibidos em seus logs. O comportamento padrão depende do tipo de construtor que você está usando.

Quando usas um IHostApplicationBuilder, as exceções lançadas pelo teu código fluem pelo sistema sem alterações. Não precisas de outra configuração.

Application Insights

Pode configurar a sua aplicação de processo isolado para enviar logs diretamente para Application Insights. Esta configuração substitui o comportamento padrão de retransmitir registos através do host. A menos que estejas a usar o Aspire, configura a integração direta com o Application Insights porque isso dá-te controlo sobre como esses registos são emitidos.

A integração com o Application Insights não está ativada por defeito em todas as experiências de configuração. Alguns templates criam projectos Functions com os pacotes necessários e o código de arranque comentados. Se quiser usar a integração com o Application Insights, descomente estas linhas no Program.cs e no ficheiro .csproj do projecto. As instruções no restante desta seção também descrevem como habilitar a integração.

Se o seu projeto está parte de uma orquestração Aspire, ele usa OpenTelemetry para monitorização em vez disso. Não ative a integração direta do Application Insights em projetos Aspire. Em vez disso, configure o exportador OpenTelemetry do Azure Monitor como parte do projeto de predefinições de serviço . Se o seu projeto Functions utiliza integração com o Application Insights num contexto Aspire, os erros da aplicação ocorrem no arranque.

Instalar pacotes

Para escrever logs diretamente no Application Insights a partir do seu código, adicione referências a estes pacotes no seu project:

Execute os seguintes comandos para adicionar estas referências ao seu project:

dotnet add package Microsoft.ApplicationInsights.WorkerService
dotnet add package Microsoft.Azure.Functions.Worker.ApplicationInsights

Configurar inicialização

Após instalar os pacotes, chame AddApplicationInsightsTelemetryWorkerService() e ConfigureFunctionsApplicationInsights() durante a configuração do serviço no seu Program.cs ficheiro, como mostrado no seguinte exemplo:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
    
var builder = FunctionsApplication.CreateBuilder(args);

builder.Services
    .AddApplicationInsightsTelemetryWorkerService()
    .ConfigureFunctionsApplicationInsights();

builder.Build().Run();

A chamada para ConfigureFunctionsApplicationInsights() adiciona um ITelemetryModule que ouve um ActivitySource definido por funções. Este módulo cria a telemetria de dependências necessária para suportar o rastreio distribuído. Para mais informações sobre AddApplicationInsightsTelemetryWorkerService() e como o utilizar, consulte Application Insights for Worker Service Applications.

Gerir níveis de registo

Importante

O anfitrião Functions e o trabalhador de processo isolado têm configurações separadas para os níveis de log. Qualquer configuração do Application Insights no host.json não afeta o registo do trabalhador e, da mesma forma, a configuração no teu código de trabalhador não afeta o registo do anfitrião. Aplica alterações em ambos os locais se o teu cenário exigir personalização em ambas as camadas.

O resto do seu aplicativo continua a funcionar com ILogger e ILogger<T>. No entanto, por padrão, o SDK do Application Insights adiciona um filtro de log que instrui o registrador a capturar apenas avisos e logs mais severos. Pode configurar os níveis de registo no processo de trabalhador isolado de uma das seguintes formas:

Método de configuração Benefícios
No teu código Promove uma separação mais clara entre as configurações do lado do host e no lado do trabalhador.
Ao utilizar appsettings.json Útil quando queres definir diferentes níveis de log para diferentes categorias sem teres de modificar o teu código.

Para desativar o comportamento predefinido e capturar todos os níveis de log, remova a regra do filtro como parte da configuração do serviço:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Builder;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

var builder = FunctionsApplication.CreateBuilder(args);

builder.Services
    .AddApplicationInsightsTelemetryWorkerService()
    .ConfigureFunctionsApplicationInsights();

builder.Logging.Services.Configure<LoggerFilterOptions>(options =>
    {
        LoggerFilterRule? defaultRule = options.Rules.FirstOrDefault(rule => rule.ProviderName
            == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");
        if (defaultRule is not null)
        {
            options.Rules.Remove(defaultRule);
        }
    });

builder.Build().Run();

Para mais informações sobre a configuração do registo, consulte Logging in .NET e Application Insights for Worker Service Applications.

Otimizações de desempenho

Esta secção descreve as opções que pode ativar e que melhoram o desempenho durante o arranque a frio.

Em geral, seu aplicativo deve usar as versões mais recentes de suas dependências principais. No mínimo, atualize o seu project da seguinte forma:

  1. Atualizar Microsoft. Azure. Functions.Worker para a versão 1.19.0 ou posterior.
  2. Atualizar Microsoft. Azure. Functions.Worker.Sdk para a versão 1.16.4 ou posterior.
  3. Adicione uma referência de framework a Microsoft.AspNetCore.App, a menos que a sua aplicação tenha como objetivo .NET Framework.

O excerto seguinte mostra esta configuração no contexto de um ficheiro de project:

  <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.16.4" />
  </ItemGroup>

Marcadores de Posição

Os marcadores de posição são uma funcionalidade de plataforma que melhora o arranque a frio para aplicações direcionadas a .NET 6 ou posteriores. Para usar esta otimização, deve ativar explicitamente os marcadores de posição seguindo estes passos:

  1. Atualize a configuração do seu project para usar as versões mais recentes de dependências, conforme detalhado na secção anterior.

  2. Defina a configuração da WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED aplicação para 1. Use este comando az functionapp config appsettings set:

    az functionapp config appsettings set -g <groupName> -n <appName> --settings 'WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED=1'
    

    Neste exemplo, substitua <groupName> pelo nome do grupo de recursos e substitua <appName> pelo nome do seu aplicativo de função.

  3. Certifique-se de que a propriedade netFrameworkVersion da aplicação de funções corresponde ao framework alvo do seu project, que deve ser .NET 6 ou posterior. Use este comando az functionapp config set:

    az functionapp config set -g <groupName> -n <appName> --net-framework-version <framework>
    

    Neste exemplo, substitua também <framework> pela string de versão apropriada, como v8.0, de acordo com a sua versão .NET alvo.

  4. Certifique-se de que a sua aplicação de funções está configurada para usar um processo de 64 bits. Use este comando az functionapp config set:

    az functionapp config set -g <groupName> -n <appName> --use-32bit-worker-process false
    

Importante

Ao definir WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED para 1, deve configurar corretamente todas as outras definições da aplicação de função. Caso contrário, seu aplicativo de função pode falhar ao iniciar.

Executor otimizado

O executor de função é um componente da plataforma que faz com que as invocações sejam executadas. Uma versão otimizada desse componente é habilitada por padrão a partir da versão 1.16.2 do SDK. Nenhuma outra configuração é necessária.

ReadyToRun

Você pode compilar a sua app de função como binários ReadyToRun. ReadyToRun é uma forma de compilação antecipada que pode melhorar o desempenho de inicialização para ajudar a reduzir o efeito de arranques a frio ao executar num Plano de Consumo. O ReadyToRun está disponível em versões .NET 6 e posteriores e requer versão 4.0 ou posterior do tempo de execução Azure Functions.

O ReadyToRun exige que construas o project contra a arquitetura de runtime da aplicação de alojamento. Quando estas arquiteturas não estão alinhadas, a sua aplicação encontra um erro no arranque. Selecione seu identificador de tempo de execução nesta tabela:

Sistema operativo Aplicação é de 32 bits1 Identificador de tempo de execução
Windows Verdade win-x86
Windows Falso win-x64
Linux Verdade N/D (não suportado)
Linux Falso linux-x64

1 Apenas as aplicações de 64 bits são elegíveis para outras otimizações de desempenho.

Para verificar se o seu Windows app é de 32 bits ou 64 bits, execute o comando CLI seguinte, substituindo <group_name> pelo nome do seu grupo de recursos e <app_name> pelo nome da sua aplicação. Uma saída de "true" indica que a aplicação é de 32 bits e "false" indica 64 bits.

 az functionapp config show -g <group_name> -n <app_name> --query "use32BitWorkerProcess"

Você pode alterar seu aplicativo para 64 bits com o seguinte comando, usando as mesmas substituições:

az functionapp config set -g <group_name> -n <app_name> --use-32bit-worker-process false`

Para compilar o seu projeto como ReadyToRun, atualize o seu ficheiro de projeto adicionando os elementos <PublishReadyToRun> e <RuntimeIdentifier>. O exemplo a seguir mostra uma configuração para publicação em um aplicativo de função de 64 bits do Windows.

<PropertyGroup>
  <TargetFramework>net8.0</TargetFramework>
  <AzureFunctionsVersion>v4</AzureFunctionsVersion>
  <RuntimeIdentifier>win-x64</RuntimeIdentifier>
  <PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>

Se não quiseres definir o <RuntimeIdentifier> como parte do ficheiro project, também podes configurar esta definição como parte do próprio gesto de publicação. Por exemplo, numa aplicação de funções Windows de 64 bits, o comando .NET CLI é:

dotnet publish --runtime win-x64

Em Visual Studio, defina a opção Target Runtime no perfil de publicação com o identificador correto de runtime. Quando definido como o valor padrão de Portable, ReadyToRun não é usado.

Desdobrar nas Azure Functions

Quando implementas o teu projeto de código de função no Azure, ele deve ser executado numa aplicação de funções ou num contentor Linux. Tens de criar a aplicação de funções e outros recursos Azure necessários antes de implementares o teu código.

Você também pode implantar seu aplicativo de função em um contêiner Linux. Para mais informações, consulte Trabalhar com contentores e Azure Functions.

Criar recursos do Azure

Pode criar a sua aplicação de funções e outros recursos necessários no Azure usando um destes métodos:

  • Visual Studio: Visual Studio pode criar recursos para si durante o processo de publicação de código.
  • Visual Studio Code: O Visual Studio Code pode ligar-se à sua subscrição, criar os recursos necessários à sua aplicação e depois publicar o seu código.
  • Azure CLI: Use o Azure CLI para criar os recursos necessários em Azure.
  • Azure PowerShell: Use Azure PowerShell para criar os recursos necessários em Azure.
  • Templates de implementação: Utilize templates ARM e ficheiros Bicep para automatizar a implementação dos recursos necessários para Azure. Certifique-se de que o seu modelo inclui todas as definições necessárias.
  • Azure portal: Crie os recursos necessários no Azure portal.

Publicar a aplicação

Depois de criar a sua aplicação de funções e outros recursos necessários no Azure, implemente o projeto de código no Azure usando um destes métodos:

Para mais informações, consulte Tecnologias de implementação em Azure Functions.

Carga de implantação

Muitos dos métodos de implementação usam um arquivo zip. Se criar o arquivo zip por si próprio, ele deve seguir a estrutura descrita nesta secção. Se não acontecer, a sua aplicação pode apresentar erros no arranque.

A carga útil de implantação deve corresponder ao resultado de um comando dotnet publish, mas sem incluir a pasta principal. O arquivo zip deve ser feito a partir dos seguintes arquivos:

  • .azurefunctions/
  • extensions.json
  • functions.metadata
  • host.json
  • worker.config.json
  • O executável do seu projeto (uma aplicação de consola)
  • Outros arquivos e diretórios de suporte são correspondentes a esse executável

O processo de compilação gera estes ficheiros, e não deves editá-los diretamente.

Gorjeta

Podes usar o func pack comando no Core Tools para gerar corretamente um arquivo zip para deployment. O suporte para func pack está atualmente em versão de avaliação.

Ao preparar um arquivo zip para implementação, comprima apenas o conteúdo do diretório de saída, e não o diretório envolvente. Quando o arquivo é extraído para o diretório de trabalho atual, os ficheiros listados anteriormente precisam de ser imediatamente visíveis.

Requisitos de implantação

Para executar funções .NET no modelo de trabalhador isolado no Azure, é necessário cumprir alguns requisitos. Os requisitos dependem do sistema operativo:

Quando cria a sua aplicação de funções no Azure usando os métodos da secção anterior, estas definições obrigatórias são adicionadas para si. Ao criar esses recursos usando modelos ARM ou arquivos Bicep para automação, certifique-se de defini-los no modelo.

Aspire

Aspire é uma stack estruturada que simplifica o desenvolvimento de aplicações distribuídas na nuvem. Pode recrutar projetos de modelo de trabalhador isolados nas orquestrações do Aspire 13. Consulte Azure Functions com Aspire para mais informações.

Depuração

Ao executar localmente usando o Visual Studio ou o Visual Studio Code, consegues depurar o teu projeto de trabalhador isolado .NET normalmente. No entanto, há dois cenários de debugging que não funcionam como esperado.

Depuração Remota usando Visual Studio

Como seu aplicativo de processo de trabalho isolado é executado fora do tempo de execução do Functions, você precisa anexar o depurador remoto a um processo separado. Para saber mais sobre depuração usando Visual Studio, veja Depuração Remota.

Depuração ao direcionar o .NET Framework

Se o seu projeto isolado destina-se ao .NET Framework 4.8, precisa de tomar medidas manuais para ativar a depuração. Essas etapas não são necessárias se estiver usando outra estrutura de destino.

Seu aplicativo deve começar com uma chamada para FunctionsDebugger.Enable(); como sua primeira operação. Isso ocorre no método Main() antes de inicializar um HostBuilder. Seu Program.cs arquivo deve ser semelhante a este:

using System;
using System.Diagnostics;
using Microsoft.Extensions.Hosting;
using Microsoft.Azure.Functions.Worker;
using NetFxWorker;

namespace MyDotnetFrameworkProject
{
    internal class Program
    {
        static void Main(string[] args)
        {
            FunctionsDebugger.Enable();

            var host = FunctionsApplication
                .CreateBuilder(args)
                .Build();

            host.Run();
        }
    }
}

De seguida, precisa de ligar manualmente ao processo usando um depurador .NET Framework. O Visual Studio ainda não faz isto automaticamente para aplicações do .NET Framework com processos de trabalho isolados, e deve-se evitar a operação "Iniciar Depuração".

No seu diretório de project (ou no diretório de saída da compilação), execute:

func host start --dotnet-isolated-debug

Isso inicia o trabalhador e o processo para com a seguinte mensagem:

Azure Functions .NET Worker (PID: <process id>) initialized in debug mode. Waiting for debugger to attach...

Onde <process id> é a ID do seu processo de trabalho. Agora pode usar o Visual Studio para ligar manualmente ao processo. Para obter instruções sobre esta operação, consulte Como anexar a um processo em execução.

Depois que o depurador for ligado, a execução do processo será retomada e você terá a possibilidade de depurar.

Versões em pré-lançamento do .NET

Antes de um lançamento geralmente disponível, uma versão .NET pode ser lançada num estado Prévia ou Go-live. Consulte a Política Oficial de Apoio .NET para mais detalhes sobre estes estados.

Embora possa ser possível direcionar uma dada versão de um projeto do Functions local, as aplicações de funções no Azure podem não ter essa versão disponível. O Azure Functions só pode ser usado com versões Preview ou Go-live indicadas nesta secção.

O Azure Functions atualmente não funciona com nenhuma versão .NET "Preview" ou "Go-live". Consulte Versões suportadas para obter uma lista das versões geralmente disponíveis que você pode usar.

Usar um SDK .NET de pré-visualização

Para usar o Azure Functions com uma versão de pré-visualização do .NET, precisa de atualizar o seu projecto através de:

  1. Instalar a versão relevante do SDK .NET no teu desenvolvimento
  2. Alterar a TargetFramework definição no ficheiro .csproj

Quando implementa na sua aplicação de funções no Azure, também precisa garantir que o framework está disponível para a aplicação. Durante o período de pré-visualização, algumas ferramentas e experiências podem não mostrar a nova versão de pré-visualização como opção. Se não vir a versão de pré-visualização incluída no portal do Azure, pode, por exemplo, usar a API REST, ficheiros Bicep ou a Azure CLI para configurar manualmente a versão.

Para aplicações alojadas no Windows, use o seguinte comando Azure CLI. Substitua <groupName> pelo nome do grupo de recursos e substitua <appName> pelo nome do seu aplicativo de função. Substitua <framework> pela cadeia de caracteres de versão apropriada, como v8.0.

az functionapp config set -g <groupName> -n <appName> --net-framework-version <framework>

Considerações para usar versões de pré-visualização .NET

Tenha estas considerações em mente ao usar Funções com versões pré-visualizadas do .NET:

  • Quando cria as suas funções em Visual Studio, deve usar Visual Studio Insiders, que suporta a construção de projetos de Azure Functions com SDKs de pré-visualização .NET.

  • Certifique-se de que tem as ferramentas e modelos mais recentes do Functions. Para atualizar suas ferramentas:

    1. Navegue até Tools>Options, escolha Azure Functions em Projects and Solutions>Mais Definições.
    2. Selecione Verificar se há atualizações e instale as atualizações conforme solicitado.
  • Durante um período de pré-visualização, o seu ambiente de desenvolvimento pode ter uma versão mais recente da pré-visualização .NET do que o serviço alojado. Isso pode fazer com que seu aplicativo de função falhe quando implantado. Para resolver isso, você pode especificar a versão do SDK a ser usada no global.json.

    1. Execute o comando dotnet --list-sdks e anote a versão de visualização que está a usar atualmente durante o desenvolvimento local.
    2. Execute o dotnet new globaljson --sdk-version <SDK_VERSION> --force comando, onde <SDK_VERSION> é a versão que você está usando localmente. Por exemplo, dotnet new globaljson --sdk-version dotnet-sdk-10.0.100-preview.5.25277.114 --force faz com que o sistema use o SDK .NET 10 Preview 5 ao construir o seu project.

Nota

Devido ao carregamento just-in-time de estruturas de visualização, os aplicativos de função executados no Windows podem experimentar tempos de inicialização a frio aumentados quando comparados com versões anteriores do GA.

Próximos passos