Partilhar via


Guia para executar o C# Azure Functions no modelo de trabalho isolado

Este artigo é uma introdução ao trabalho com o Azure Functions no .NET, usando o modelo de trabalhador isolado. Esse modelo permite que seu projeto direcione versões do .NET independentemente de outros componentes de tempo de execução. Para obter informações sobre versões específicas do .NET suportadas, consulte a versão suportada.

Use os links a seguir para começar imediatamente a criar funções de modelo de trabalho isoladas do .NET.

Introdução Conceitos Exemplos

Para saber exatamente sobre como implantar um projeto de modelo de trabalho isolado no Azure, consulte Implantar no Azure Functions.

Benefícios do modelo de trabalhador isolado

Há dois modos nos quais você pode executar suas funções de biblioteca de classes .NET: no mesmo processo que o tempo de execução do host Functions (em processo) ou em um processo de trabalho isolado. Quando suas funções .NET são executadas em um processo de trabalho isolado, você pode aproveitar os 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 de dependência padrão: Como você tem controle total do processo, pode usar os comportamentos atuais do .NET para injeção de dependência e incorporar middleware em seu aplicativo de função.
  • Flexibilidade de versão do .NET: A execução fora do processo do host significa que suas funções podem ser executadas em versões do .NET não suportadas nativamente pelo tempo de execução do 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 obter mais informações, consulte Migrar aplicativos .NET do modelo em processo para o modelo de trabalho isolado.

Para obter uma comparação abrangente entre os dois modos, consulte Diferenças entre o processo de trabalho em processo e o processo de trabalho isolado .NET Azure Functions.

Versões suportadas

As versões do tempo de execução do Functions suportam versões específicas do .NET. Para saber mais sobre as versões do Functions, consulte Visão geral das versões de tempo de execução do Azure Functions. 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 a seguir mostra o nível mais alto de .NET ou .NET Framework que pode ser usado com uma versão específica do Functions.

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

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

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

3 O suporte termina para a versão 1.x do tempo de execução do Azure Functions em 14 de setembro de 2026. Para obter 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 obter 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.

Para obter as últimas notícias sobre as versões do Azure Functions, incluindo a remoção de versões secundárias mais antigas específicas, monitore os anúncios do Serviço de Aplicativo do Azure.

Estrutura do projeto

Um projeto .NET para o Azure Functions usando o modelo de trabalho isolado é basicamente um projeto de aplicativo de console .NET que visa um tempo de execução .NET com suporte. A seguir estão os arquivos básicos necessários em qualquer projeto isolado do .NET:

  • Arquivo 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.
  • host.json arquivo que define a configuração compartilhada por funções em seu projeto.
  • local.settings.json arquivo que define as variáveis de ambiente usadas pelo seu projeto quando executado localmente em sua máquina.

Para obter 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 usando o modelo de trabalho isolado usa um conjunto exclusivo de pacotes, para funcionalidade principal e extensões de ligação.

Pacotes principais

Os seguintes pacotes são necessários para executar suas funções .NET em um processo de trabalho isolado:

Versão 2.x

As versões 2.x dos pacotes principais alteram as estruturas suportadas e trazem suporte para novas APIs .NET dessas versões posteriores. Quando você direciona o .NET 9 ou posterior, seu aplicativo precisa fazer referência à versão 2.0.0 ou posterior de ambos os pacotes.

Ao atualizar para as versões 2.x, observe as seguintes alterações:

  • A partir da versão 2.0.0 do 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 as Ferramentas Principais do Azure Functions estão instaladas. No Windows, as Ferramentas Principais precisam ser instaladas por meio de um mecanismo diferente do NPM.
  • A partir da versão 2.0.0 do Microsoft.Azure.Functions.Worker:
    • Esta versão adiciona suporte para IHostApplicationBuilder. Alguns exemplos neste guia incluem guias para mostrar alternativas usando IHostApplicationBuildero . 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. Esse comportamento corresponde 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 essa opção ativada, as cargas úteis de gatilho que representam coleções sempre incluem entradas vazias. Por exemplo, se uma mensagem for enviada sem um corpo, uma entrada vazia ainda estará presente para string[] os dados do gatilho. 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() em uma ILogger instância.
    • Para aplicativos que usam HttpResponseDatao , o WriteAsJsonAsync() método não definirá mais o código de status como 200 OK. Em 1.x, isso substituiu outros códigos de erro que haviam sido definidos.
  • As versões 2.x descartam o suporte ao .NET 5 TFM.

Pacotes de extensão

Como as funções de processo de trabalho isoladas do .NET usam tipos de vinculação diferentes, elas exigem um conjunto exclusivo de pacotes de extensão de vinculação.

Você encontra esses pacotes de extensão em Microsoft.Azure.Functions.Worker.Extensions.

Arranque e configuração

Ao usar o modelo de trabalho isolado, você tem acesso à inicialização do seu aplicativo de função, que geralmente está em Program.cs. Você é responsável por criar e iniciar sua própria instância de host. Como tal, você também tem acesso direto ao pipeline de configuração do seu aplicativo. Com o processo de trabalho isolado do .NET Functions, você pode adicionar configurações muito mais facilmente, injetar dependências e executar seu próprio middleware.

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

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(s =>
    {
        s.AddApplicationInsightsTelemetryWorkerService();
        s.ConfigureFunctionsApplicationInsights();
        s.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();
        s.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/en-us/azure/azure-monitor/app/worker-service#ilogger-logs
            LoggerFilterRule? toRemove = options.Rules.FirstOrDefault(rule => rule.ProviderName
                == "Microsoft.Extensions.Logging.ApplicationInsights.ApplicationInsightsLoggerProvider");

            if (toRemove is not null)
            {
                options.Rules.Remove(toRemove);
            }
        });
    })
    .Build();

Este código requer using Microsoft.Extensions.DependencyInjection;.

Antes de recorrer Build() ao IHostBuilder, deverá:

  • Ligue se ConfigureFunctionsWebApplication() estiver usando a integração ASP.NET Core ou ConfigureFunctionsWorkerDefaults() de outra forma. Consulte Gatilho HTTP para obter detalhes sobre essas opções.
    Se você estiver escrevendo seu aplicativo usando F#, algumas extensões de gatilho e vinculação exigirão configuração extra. Consulte a documentação de configuração da extensão Blobs, da extensão Tables e da extensão Cosmos DB quando planeja usar essas extensões em um aplicativo F#.
  • Configure qualquer configuração de serviço ou aplicativo que seu projeto exija. Consulte Configuração para obter detalhes.
    Se você estiver planejando usar o Application Insights, precisará ligar AddApplicationInsightsTelemetryWorkerService() para o ConfigureFunctionsApplicationInsights() ConfigureServices() delegado. Consulte Application Insights para obter detalhes.

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

O HostBuilder é 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 você usa determina como você pode configurar o aplicativo.

O método ConfigureFunctionsWorkerDefaults é usado para adicionar as configurações necessárias para que o aplicativo de função seja executado. O método inclui a seguinte funcionalidade:

  • Conjunto padrão de conversores.
  • Defina o padrão JsonSerializerOptions para ignorar a caixa em nomes de propriedade.
  • Integre com o registo do Azure Functions.
  • Middleware e recursos de vinculação de saída.
  • Middleware de execução de funções.
  • Suporte padrão a gRPC.
.ConfigureFunctionsWorkerDefaults()

Ter acesso ao pipeline do construtor de hosts significa que você também pode definir quaisquer configurações específicas do aplicativo durante a inicialização. Você pode chamar o método ConfigureAppConfiguration no HostBuilder uma ou mais vezes para adicionar quaisquer fontes de configuração exigidas pelo seu código. Para saber mais sobre a configuração do aplicativo, consulte Configuração no ASP.NET Core.

Essas configurações só se aplicam ao código de trabalho criado e não influenciam diretamente a configuração do host Functions ou acionadores e associações. Para fazer alterações nas funções host ou configuração de gatilho e vinculação, você ainda precisa usar o arquivo host.json.

Nota

As fontes de configuração personalizadas não podem ser usadas para a configuração de gatilhos e associações. 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. Você pode fornecer essa configuração por meio das configurações do aplicativo, referências do Cofre da Chave ou recursos de referências de Configuração do Aplicativo.

Injeção de dependência

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

Quando você usa um HostBuilder, chame ConfigureServices no construtor de host e use os métodos de extensão em IServiceCollection para injetar serviços específicos. O exemplo a seguir injeta uma dependência de serviço singleton:

.ConfigureServices(services =>
{
    services.AddSingleton<IHttpResponderService, DefaultHttpResponderService>();
})

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

Registrar clientes do Azure

A injeção de dependência pode ser usada para interagir com outros serviços do Azure. Você pode injetar clientes do SDK do Azure para .NET usando o pacote Microsoft.Extensions.Azure . Depois de instalar o pacote, registre os clientes chamando AddAzureClients() a coleção de serviços em Program.cs. O exemplo a seguir configura um cliente nomeado para Blobs do Azure:

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

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices((hostContext, services) =>
    {
        services.AddAzureClients(clientBuilder =>
        {
            clientBuilder.AddBlobServiceClient(hostContext.Configuration.GetSection("MyStorageConnection"))
                .WithName("copierOutputBlob");
        });
    })
    .Build();

host.Run();

O exemplo a seguir mostra como podemos usar esses tipos de registro e SDK para copiar o conteúdo do blob como um fluxo de um contêiner 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 foi obtido através da injeção de dependência, por isso é registrado automaticamente. Para saber mais sobre as opções de configuração para registro em log, consulte Logging.

Gorjeta

O exemplo usou uma cadeia de caracteres literal para o nome do cliente em ambos Program.cs e a função. Em vez disso, considere usar uma cadeia de caracteres constante compartilhada definida na classe de função. 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 registro de middleware, novamente usando um modelo semelhante ao que existe no ASP.NET. Esse modelo oferece a capacidade de injetar lógica no pipeline de invocação e executar funções antes e depois.

O método de extensão ConfigureFunctionsWorkerDefaults tem uma sobrecarga que permite registrar seu próprio middleware, como você pode ver no exemplo a seguir.

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(workerApplication =>
    {
        // Register our custom middlewares with the worker

        workerApplication.UseMiddleware<ExceptionHandlingMiddleware>();

        workerApplication.UseMiddleware<MyCustomMiddleware>();

        workerApplication.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";
        });
    })
    .Build();

O UseWhen método de extensão pode ser usado para registrar um middleware que é executado condicionalmente. Você deve passar para esse método um predicado que retorna um valor booleano, e o middleware participa do pipeline de processamento de invocação quando o valor de retorno do predicado é true.

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

Método Description
GetHttpRequestDataAsync Obtém a instância quando chamada por um gatilho HttpRequestData HTTP. Esse método retorna uma instância de , que é útil quando você deseja ler dados de mensagem, como cabeçalhos de ValueTask<HttpRequestData?>solicitação e cookies.
GetHttpResponseData Obtém a instância quando chamada por um gatilho HttpResponseData 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, você pode usar esse método quando tiver uma função com uma BlobInput ligação de entrada que precisa ser usada pelo middleware.

Este é um exemplo de uma implementação de middleware que lê a HttpRequestData instância e atualiza a instância durante a execução da HttpResponseData 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);
    }
}

Esse middleware verifica a presença de um cabeçalho de solicitação específico (x-correlationId) e, quando presente, usa o valor do cabeçalho para carimbar um cabeçalho de resposta. Caso contrário, ele gera um novo valor GUID e o usa para carimbar o cabeçalho de resposta. Para obter um exemplo mais completo de uso de middleware personalizado em seu aplicativo de função, consulte o exemplo 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 seção aborda a serialização de uso geral e não influenciará a serialização JSON de gatilho HTTP com ASP.NET integração Core, que deve ser configurada separadamente.

O exemplo a seguir mostra isso usando ConfigureFunctionsWebApplicationo , mas também funcionará para ConfigureFunctionsWorkerDefaults:

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

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication((IFunctionsWorkerApplicationBuilder builder) =>
    {
        builder.Services.Configure<JsonSerializerOptions>(jsonSerializerOptions =>
        {
            jsonSerializerOptions.PropertyNamingPolicy = JsonNamingPolicy.CamelCase;
            jsonSerializerOptions.DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull;
            jsonSerializerOptions.ReferenceHandler = ReferenceHandler.Preserve;

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

host.Run();

Em vez disso, você pode usar JSON.NET (Newtonsoft.Json) para serialização. Para fazer isso, você deve instalar o Microsoft.Azure.Core.NewtonsoftJson pacote. Em seguida, no registro do serviço, você reatribuiria a Serializer propriedade na WorkerOptions configuração. O exemplo a seguir mostra isso usando ConfigureFunctionsWebApplicationo , mas também funcionará para ConfigureFunctionsWorkerDefaults:

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

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

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

host.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(QueueFunction))]
[QueueOutput("output-queue")]
public string[] Run([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 é acionada 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 exclusivo dentro de um projeto, começar com uma letra e conter apenas letras, _números e -, até 127 caracteres de comprimento. Os modelos de projeto geralmente criam um método chamado Run, mas o nome do método pode ser qualquer nome de método C# válido. 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 normal.

Contexto de execução

O .NET isolado passa um objeto FunctionContext para seus métodos de função. Esse objeto permite que você obtenha uma ILogger instância para gravar nos logs chamando o método GetLogger e fornecendo uma categoryName cadeia de caracteres. Você pode usar esse contexto para obter um ILogger sem ter que usar a injeção de dependência. Para saber mais, 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.

Os tokens de cancelamento são suportados em funções .NET quando executados em um processo de trabalho isolado. 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);
    }
}

Enlaces

As ligações são definidas 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 obter um conjunto completo de exemplos de referência usando gatilhos e associações com funções isoladas do processo de trabalho, consulte o exemplo de referência de extensões de ligação.

Enlaces de entrada

Uma função pode ter zero ou mais ligações de entrada que podem passar dados para uma função. Como os gatilhos, as ligações de entrada são definidas aplicando um atributo de ligação a um parâmetro de entrada. Quando a função é executada, o tempo de execução tenta obter dados especificados na ligação. Os dados solicitados dependem frequentemente das informações fornecidas pelo gatilho usando parâmetros de vinculação.

Enlaces de saída

Para gravar em uma ligação de saída, você deve aplicar um atributo de vinculação de saída ao método function, que define como gravar no serviço vinculado. O valor retornado pelo método é gravado na associaçã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(QueueFunction))]
[QueueOutput("output-queue")]
public string[] Run([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;
}

Várias ligaçõ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 a seguir é uma função acionada por HTTP usando a integração ASP.NET Core que grava na resposta HTTP e em uma ligação de saída de 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; }
    }
}

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

Tipos de SDK

Para alguns tipos de associação específicos de serviço, os dados de associação podem ser fornecidos usando tipos de SDKs e estruturas de serviço. Eles fornecem mais recursos além do que uma cadeia de caracteres serializada ou um objeto CLR antigo (POCO) pode oferecer. Para usar os tipos mais recentes, seu projeto precisa ser atualizado para usar versões mais recentes das dependências principais.

Dependency 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 tipos de SDK localmente em sua máquina, você também precisa usar as Ferramentas Principais do Azure Functions, versão 4.0.5000 ou posterior. Você pode verificar sua versão atual usando o func version comando.

Cada extensão de acionamento e vinculação também tem seu próprio requisito de versão mínima, que é descrito nos artigos de referência de extensão. As seguintes associações específicas de serviço fornecem tipos de SDK:

Serviço Acionador Vinculação de entrada Vinculação de saída
Azure Blobs Geralmente disponível Geralmente disponível Tipos de SDK não recomendados.1
Filas do Azure Geralmente disponível A vinculação de entrada não existe Tipos de SDK não recomendados.1
Azure Service Bus Geralmente disponível A vinculação de entrada não existe Tipos de SDK não recomendados.1
Hubs de Eventos do Azure Geralmente disponível A vinculação de entrada não existe Tipos de SDK não recomendados.1
BD do Cosmos para o Azure Tipos de SDK não utilizados2 Geralmente disponível Tipos de SDK não recomendados.1
Tabelas do Azure O gatilho não existe Geralmente disponível Tipos de SDK não recomendados.1
Azure Event Grid Geralmente disponível A vinculação de entrada não existe Tipos de SDK não recomendados.1

1 Para cenários de saída nos quais você usaria um tipo de SDK, você deve criar e trabalhar com clientes SDK diretamente em vez de usar uma associação de saída. Consulte Registrar clientes do Azure para obter um exemplo de injeção de dependência.

2 O gatilho do Cosmos DB usa o feed de alterações do Azure Cosmos DB e expõe itens de feed de alteração como tipos serializáveis por JSON. A ausência de tipos de SDK é por design para este cenário.

Nota

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.

Acionador HTTP

Os gatilhos HTTP permitem que uma função seja invocada por uma solicitação HTTP. Existem duas abordagens diferentes que podem ser usadas:

  • Um modelo de integração ASP.NET Core que usa conceitos familiares aos desenvolvedores do ASP.NET Core
  • Um modelo interno, que não requer dependências extras e usa tipos personalizados para solicitações e respostas HTTP. Essa abordagem é mantida para compatibilidade com versões anteriores de aplicativos de trabalho isolados do .NET.

Integração ASP.NET Core

Esta seção mostra como trabalhar com os objetos de solicitação e resposta HTTP subjacentes usando tipos do ASP.NET Core, incluindo HttpRequest, HttpResponse e IActionResult. Esse modelo não está disponível para aplicativos destinados ao .NET Framework, que devem usar o modelo interno.

Nota

Nem todos os recursos do ASP.NET Core são expostos por esse modelo. Especificamente, o pipeline de middleware ASP.NET Core e os recursos de roteamento não estão disponíveis. ASP.NET integração Core requer que você use pacotes atualizados.

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

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

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

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

    using Microsoft.Azure.Functions.Worker;
    using Microsoft.Extensions.Hosting;
    
    var host = new HostBuilder()
        .ConfigureFunctionsWebApplication()
        .Build();
    
    host.Run();
    
  4. Atualize todas as funções acionadas por HTTP existentes para usar 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 sua própria camada de serialização e não é afetada pela 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 retornado IMvcBuilder pode ser usado para modificar as configurações de serialização JSON do ASP.NET Core.

Você pode continuar a usar HttpRequestData e HttpResponsedata , ao usar ASP.NET integração, embora para a maioria dos aplicativos, seja melhor usar HttpRequest e IActionResult. O uso HttpRequestData/HttpResponseData não invoca a camada de serialização ASP.NET Core e, em vez disso, depende da configuração geral de serialização do trabalhador para o aplicativo. No entanto, quando a integração do ASP.NET Core estiver habilitada, talvez ainda seja necessário adicionar a configuração. O comportamento padrão do ASP.NET Core é não permitir E/S síncrona. Para usar um serializador personalizado que não ofereça suporte a E/S assíncrona, como NewtonsoftJsonObjectSerializer, você precisa habilitar a E/S síncrona para seu aplicativo configurando o KestrelServerOptions.

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

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

var host = new HostBuilder()
    .ConfigureFunctionsWebApplication()
    .ConfigureServices(services =>
    {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
        services.AddMvc().AddNewtonsoftJson();

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

Modelo HTTP integrado

No modelo interno, o sistema converte a mensagem de solicitação HTTP de entrada em um objeto HttpRequestData que é passado para a função. Este objeto fornece dados da solicitação, incluindo Headers, , , IdentitieseURL, opcionalmente, uma mensagem BodyCookies. Este objeto é uma representação da solicitação HTTP, mas não está diretamente conectado ao ouvinte HTTP subjacente ou à mensagem recebida.

Da mesma forma, a função retorna um objeto HttpResponseData , que fornece dados usados para criar a resposta HTTP, incluindo a mensagem StatusCode, Headerse, 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 uma ILogger<T> instância ou ILogger . O logger pode ser obtido 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}");
    }

}

O logger também pode ser obtido de um objeto FunctionContext passado para sua função. Chame o método GetLogger<T> ou GetLogger , passando um valor de cadeia de caracteres que é o nome da categoria na qual os logs são gravados. A categoria é geralmente o nome da função específica a partir da qual os logs são gravados. Para saber mais sobre categorias, consulte o artigo de monitoramento.

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

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

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services =>
    {
        // Registers IHttpClientFactory.
        // By default this sends a lot of Information-level logs.
        services.AddHttpClient();
    })
    .ConfigureLogging(logging =>
    {
        // Disable IHttpClientFactory Informational logs.
        // Note -- you can also remove the handler that does the logging: https://github.com/aspnet/HttpClientFactory/issues/196#issuecomment-432755765 
        logging.AddFilter("System.Net.Http.HttpClient", LogLevel.Warning);
    })
    .Build();

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 você usa um HostBuilder, por padrão, as exceções lançadas pelo seu código podem acabar embrulhadas em um RpcExceptionarquivo . Para remover essa camada extra, defina a EnableUserCodeException propriedade como "true" como parte da configuração do construtor:

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

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults(builder => {}, options =>
    {
        options.EnableUserCodeException = true;
    })
    .Build();

host.Run();

Application Insights

Você pode configurar seu aplicativo de processo isolado para emitir logs diretamente para o Application Insights. Esse comportamento substitui o comportamento padrão de retransmissão de logs através do host. A menos que você esteja usando o .NET Aspire, a configuração da integração direta do Application Insights é recomendada porque oferece controle sobre como esses logs são emitidos.

A integração do Application Insights não está habilitada por padrão em todas as experiências de configuração. Alguns modelos criarão projetos do Functions com os pacotes necessários e o código de inicialização comentado. Se quiser usar a integração do Application Insights, você pode descomentar essas linhas e Program.cs o arquivo do .csproj projeto. As instruções no restante desta seção também descrevem como habilitar a integração.

Se o seu projeto fizer parte de uma orquestração do .NET Aspire em vez disso, ele usará OpenTelemetry para monitoramento. Você não deve habilitar a integração direta do Application Insights em projetos do .NET Aspire . Em vez disso, configure o exportador do Azure Monitor OpenTelemetry como parte do projeto de padrões de serviço. Se o seu projeto do Functions usar a integração do Application Insights em um contexto do .NET Aspire , o aplicativo ocorrerá um erro na inicialização.

Instalar pacotes

Para gravar logs diretamente no Application Insights a partir do seu código, adicione referências a esses pacotes em seu projeto:

Você pode executar os seguintes comandos para adicionar essas referências ao seu projeto:

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

Configurar inicialização

Com os pacotes instalados, você deve chamar AddApplicationInsightsTelemetryWorkerService() e ConfigureFunctionsApplicationInsights() durante a configuração do serviço em seu Program.cs arquivo, como neste exemplo:

using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
    
var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services => {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
    })
    .Build();

host.Run();

A chamada para ConfigureFunctionsApplicationInsights() adicionar um ITelemetryModule, que escuta um Functions-defined ActivitySource. Isso cria a telemetria de dependência necessária para dar suporte ao rastreamento distribuído. Para saber mais sobre AddApplicationInsightsTelemetryWorkerService() e como usá-lo, consulte Application Insights for Worker Service applications.

Gerenciando níveis de log

Importante

O host Functions e o operador de processo isolado têm configuração separada para níveis de log, etc. Qualquer configuração do Application Insights no host.json não afetará o log do trabalhador e, da mesma forma, a configuração feita no código do trabalhador não afetará o log do host. Necessitará aplicar alterações em ambos os locais se o 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. Se desejar desabilitar esse comportamento, remova a regra de filtro como parte da configuração do serviço:

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

var host = new HostBuilder()
    .ConfigureFunctionsWorkerDefaults()
    .ConfigureServices(services => {
        services.AddApplicationInsightsTelemetryWorkerService();
        services.ConfigureFunctionsApplicationInsights();
    })
    .ConfigureLogging(logging =>
    {
        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);
            }
        });
    })
    .Build();

host.Run();

Otimizações de desempenho

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

Em geral, seu aplicativo deve usar as versões mais recentes de suas dependências principais. No mínimo, você deve atualizar seu projeto da seguinte maneira:

  1. Atualize o Microsoft.Azure.Functions.Worker para a versão 1.19.0 ou posterior.
  2. Atualize Microsoft.Azure.Functions.Worker.Sdk para a versão 1.16.4 ou posterior.
  3. Adicione uma referência de estrutura ao , a menos que seu aplicativo tenha como destino o Microsoft.AspNetCore.App.NET Framework.

O trecho a seguir mostra essa configuração no contexto de um arquivo de projeto:

  <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 espaços reservados são um recurso de plataforma que melhora o arranque a frio para aplicações destinadas ao .NET 6 ou posterior. Para usar essa otimização, você deve habilitar explicitamente os espaços reservados usando estas etapas:

  1. Atualize a configuração do projeto para usar as versões de dependência mais recentes, conforme detalhado na seção anterior.

  2. Defina a configuração do WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED aplicativo como , o 1que você pode fazer usando 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. Verifique se a netFrameworkVersion propriedade do aplicativo de função corresponde à estrutura de destino do seu projeto, que deve ser .NET 6 ou posterior. Você pode fazer isso usando este comando az functionapp config set :

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

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

  4. Certifique-se de que seu aplicativo de função está configurado para usar um processo de 64 bits, o que você pode fazer usando este comando az functionapp config set :

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

Importante

Ao definir o WEBSITE_USE_PLACEHOLDER_DOTNETISOLATED para 1, todas as outras configurações de aplicativo de função devem ser definidas corretamente. 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 seu aplicativo de função como binários ReadyToRun. O ReadyToRun é uma forma de compilação antecipada que pode melhorar o desempenho de inicialização para ajudar a reduzir o efeito de partidas a frio ao executar em um plano de consumo. O ReadyToRun está disponível no .NET 6 e versões posteriores e requer a versão 4.0 ou posterior do tempo de execução do Azure Functions.

ReadyToRun requer que você crie o projeto em relação à arquitetura de tempo de execução do aplicativo de hospedagem. Se eles não estiverem alinhados, seu aplicativo encontrará um erro na inicialização. Selecione seu identificador de tempo de execução nesta tabela:

Sistema operativo App é 32-bit1 Identificador de tempo de execução
Windows True win-x86
Windows False win-x64
Linux True N/D (não suportado)
Linux False linux-x64

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

Para verificar se seu aplicativo do Windows é de 32 bits ou 64 bits, você pode executar o seguinte comando da CLI, substituindo <group_name> pelo nome do grupo de recursos e <app_name> pelo nome do aplicativo. Uma saída de "true" indica que o aplicativo é 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 seu projeto como ReadyToRun, atualize seu arquivo de projeto adicionando os <PublishReadyToRun> elementos 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 você não quiser definir o <RuntimeIdentifier> como parte do arquivo de projeto, você também pode configurá-lo como parte do gesto de publicação em si. Por exemplo, com um aplicativo de função de 64 bits do Windows, o comando .NET CLI seria:

dotnet publish --runtime win-x64

No Visual Studio, a opção Target Runtime no perfil de publicação deve ser definida como o identificador de tempo de execução correto. Quando definido como o valor padrão de Portable, ReadyToRun não é usado.

Implementar para as Funções do Azure

Quando você implanta seu projeto de código de função no Azure, ele deve ser executado em um aplicativo de função ou em um contêiner Linux. O aplicativo de função e outros recursos necessários do Azure devem existir antes de implantar seu código.

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

Criar recursos do Azure

Você pode criar seu aplicativo de função e outros recursos necessários no Azure usando um destes métodos:

  • Visual Studio: Visual Studio pode criar recursos para você durante o processo de publicação de código.
  • Visual Studio Code: o Visual Studio Code pode se conectar à sua assinatura, criar os recursos necessários para seu aplicativo e, em seguida, publicar seu código.
  • CLI do Azure: você pode usar a CLI do Azure para criar os recursos necessários no Azure.
  • Azure PowerShell: Você pode usar o Azure PowerShell para criar os recursos necessários no Azure.
  • Modelos de implantação: você pode usar modelos ARM e arquivos Bicep para automatizar a implantação dos recursos necessários no Azure. Certifique-se de que o seu modelo inclui todas as definições necessárias.
  • Portal do Azure: você pode criar os recursos necessários no portal do Azure.

Publicar a aplicação

Depois de criar seu aplicativo de função e outros recursos necessários no Azure, você pode implantar o projeto de código no Azure usando um destes métodos:

  • Visual Studio: Implantação manual simples durante o desenvolvimento.
  • Visual Studio Code: Implantação manual simples durante o desenvolvimento.
  • Ferramentas principais do Azure Functions: implante o arquivo de projeto a partir da linha de comando.
  • Implantação contínua: Útil para manutenção contínua, freqüentemente para um slot de preparação.
  • Modelos de implantação: você pode usar modelos ARM ou arquivos Bicep para automatizar implantações de pacotes.

Para obter mais informações, consulte Tecnologias de implantação no Azure Functions.

Carga útil de implantação

Muitos dos métodos de implantação fazem uso de um arquivo zip. Se você estiver criando o arquivo zip por conta própria, ele deve seguir a estrutura descrita nesta seção. Se isso não acontecer, seu aplicativo pode ter erros na inicialização.

A carga útil de implantação deve corresponder à saída de um dotnet publish comando, embora sem a pasta pai que a inclui. O arquivo zip deve ser feito a partir dos seguintes arquivos:

  • .azurefunctions/
  • extensions.json
  • functions.metadata
  • host.json
  • worker.config.json
  • Seu executável de projeto (um aplicativo de console)
  • Outros arquivos e diretórios de suporte são correspondentes a esse executável

Esses arquivos são gerados pelo processo de compilação e não devem ser editados diretamente.

Ao preparar um arquivo zip para implantação, você deve compactar apenas o conteúdo do diretório de saída, não o diretório de fechamento em si. Quando o arquivo é extraído para o diretório de trabalho atual, os arquivos listados acima precisam ser imediatamente visíveis.

Requisitos de implantação

Há alguns requisitos para executar funções .NET no modelo de trabalho isolado no Azure, dependendo do sistema operacional:

  • FUNCTIONS_WORKER_RUNTIME deve ser definido como um valor de dotnet-isolated.
  • netFrameworkVersion deve ser definido para a versão desejada.

Quando você cria seu aplicativo de função no Azure usando os métodos na seção anterior, essas configurações necessárias são adicionadas para você. Ao criar esses recursos usando modelos ARM ou arquivos Bicep para automação, certifique-se de defini-los no modelo.

.NET Aspire (Pré-visualização)

O .NET Aspire é uma pilha opinativa que simplifica o desenvolvimento de aplicações distribuídas na nuvem. Você pode inscrever projetos de modelo de trabalho isolados do .NET 8 e .NET 9 em orquestrações do Aspire 9.0 usando o suporte à visualização. A seção descreve os principais requisitos para o alistamento.

Esta integração requer uma configuração específica:

  • Use o Aspire 9.0 ou posterior e o SDK do .NET 9. O Aspire 9.0 suporta as estruturas .NET 8 e .NET 9.
  • Se você usar o Visual Studio, atualize para a versão 17.12 ou posterior. Você também deve ter a versão mais recente das ferramentas de funções para Visual Studio. Para verificar se há atualizações, navegue até Opções de Ferramentas>, escolha Azure Functions em Projetos e Soluções. Selecione Verificar se há atualizações e instale as atualizações conforme solicitado.
  • No projeto de anfitrião da aplicação Aspir:
    • Você deve fazer referência a Aspire.Hosting.Azure.Functions.
    • Você deve ter uma referência de projeto para seu projeto de funções.
    • No host do Program.csaplicativo, você também deve incluir o projeto chamando AddAzureFunctionsProject<TProject>() o seu IDistributedApplicationBuilder. Esse método é usado em vez do que você usa para outros tipos de AddProject<TProject>() projeto. Se você apenas usar AddProject<TProject>()o , o projeto Functions não será iniciado corretamente.
  • No projeto Funções:
    • Você deve fazer referência às versões 2.x de Microsoft.Azure.Functions.Worker e Microsoft.Azure.Functions.Worker.Sdk. Você também deve atualizar quaisquer referências que você tem para Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore a versão 2.x também.
    • Você Program.cs deve usar a IHostApplicationBuilder versão de inicialização da instância do host.
    • Se pretender utilizar as predefinições do serviço Aspir, deve incluir uma referência de projeto ao projeto predefinido do serviço. Antes de construir o seu IHostApplicationBuilder , Program.csvocê também deve incluir uma chamada para builder.AddServiceDefaults().
    • Você não deve manter a configuração no local.settings.json, além da FUNCTIONS_WORKER_RUNTIME configuração, que deve permanecer "isolada por dotnet". Outra configuração deve ser definida por meio do projeto de host do aplicativo.
    • Você deve remover todas as integrações diretas do Application Insights. Em vez disso, a monitorização no Aspire é tratada através do seu suporte OpenTelemetria.

O exemplo a seguir mostra um mínimo Program.cs para um projeto de Host de Aplicativo:

var builder = DistributedApplication.CreateBuilder(args);

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject");

builder.Build().Run();

O exemplo a seguir mostra um mínimo Program.cs para um projeto Functions usado no Aspire:

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

builder.ConfigureFunctionsWebApplication();

builder.Build().Run();

Isso não inclui a configuração padrão do Application Insights que você vê em muitos dos outros Program.cs exemplos neste artigo. Em vez disso, a integração OpenTelemetry do Aspire é configurada por meio da builder.AddServiceDefaults() chamada.

Considerações e práticas recomendadas para a integração do .NET Aspire

Considere os seguintes pontos ao avaliar o .NET Aspire com o Azure Functions:

  • O suporte para o Azure Functions com o .NET Aspire está atualmente em pré-visualização. Durante o período de pré-visualização, quando publica a solução Aspire no Azure, os projetos do Functions são implementados como recursos das Aplicações de Contentor do Azure sem dimensionamento controlado por eventos. O suporte do Azure Functions não está disponível para aplicativos implantados nesse modo.
  • A configuração de acionamento e vinculação através do Aspire está atualmente limitada a integrações específicas. Consulte Configuração de ligação com o Aspire para obter detalhes.
  • Você Program.cs deve usar a IHostApplicationBuilder versão de inicialização da instância do host. Isso permite que você ligue builder.AddServiceDefaults() para adicionar padrões de serviço .NET Aspire ao seu projeto do Functions.
  • O Aspire utiliza o OpenTelemetry para monitorização. Você pode configurar o Aspire para exportar telemetria para o Azure Monitor por meio do projeto de padrões de serviço. Em muitos outros contextos do Azure Functions, você pode incluir a integração direta com o Application Insights registrando o serviço de trabalhador de telemetria. Isso não é recomendado no Aspire e pode levar a erros de tempo de execução com a versão 2.22.0 do Microsoft.ApplicationInsights.WorkerService. Você deve remover todas as integrações diretas do Application Insights do seu projeto do Functions ao usar o Aspire.
  • Para projetos do Functions inscritos numa orquestração do Aspire , a maior parte da configuração da aplicação deve provir do projeto de anfitrião da aplicação Aspir. Normalmente, você deve evitar definir coisas em local.settings.json, além da FUNCTIONS_WORKER_RUNTIME configuração. Se a mesma variável de ambiente for definida por local.settings.json e Aspire, o sistema usa a versão Aspir.
  • Não configure o emulador de armazenamento para conexões no local.settings.json. Muitos modelos iniciais do Functions incluem o emulador como padrão para AzureWebJobsStorage. No entanto, a configuração do emulador pode solicitar que alguns IDEs iniciem uma versão do emulador que pode entrar em conflito com a versão que o Aspire usa.

Configuração da ligação com o Aspire

O Azure Functions requer uma conexão de armazenamento de host (AzureWebJobsStorage) para vários de seus comportamentos principais. Quando você chama AddAzureFunctionsProject<TProject>() seu projeto de host de aplicativo, uma conexão padrão AzureWebJobsStorage é criada e fornecida ao projeto Functions. Essa conexão padrão usa o emulador de armazenamento para execução de desenvolvimento local e provisiona automaticamente uma conta de armazenamento quando implantada. Para obter controle adicional, você pode substituir essa conexão chamando .WithHostStorage() o recurso do projeto Functions.

O exemplo a seguir mostra um mínimo Program.cs para um projeto de host de aplicativo que substitui o armazenamento de host:

var builder = DistributedApplication.CreateBuilder(args);

var myHostStorage = builder.AddAzureStorage("myHostStorage");

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithHostStorage(myHostStorage);

builder.Build().Run();

Nota

Quando o Aspire provisiona o armazenamento do host no modo de publicação, o padrão é criar atribuições de função para as funções de Colaborador de Conta de Armazenamento, Colaborador de Dados de Blob de Armazenamento, Colaborador de Dados da Fila de Armazenamento e Colaborador de Dados da Tabela de Armazenamento .

Seus gatilhos e ligações fazem referência a conexões por nome. Algumas integrações do Aspire estão habilitadas para fornecê-las através de uma chamada para WithReference() o recurso do projeto:

Integração Aspire Notas
Azure Blobs Quando o Aspire provisiona o recurso, o padrão é criar atribuições de função para as funções de Colaborador de Dados de Blob de Armazenamento, Colaborador de Dados da Fila de Armazenamento e Colaborador de Dados da Tabela de Armazenamento.
Filas do Azure Quando o Aspire provisiona o recurso, o padrão é criar atribuições de função para as funções de Colaborador de Dados de Blob de Armazenamento, Colaborador de Dados da Fila de Armazenamento e Colaborador de Dados da Tabela de Armazenamento.
Hubs de Eventos do Azure Quando o Aspire provisiona o recurso, o padrão é criar uma atribuição de função usando a função Proprietário de Dados dos Hubs de Eventos do Azure.
Azure Service Bus Quando o Aspire provisiona o recurso, o padrão é criar uma atribuição de função usando a função Proprietário de Dados do Barramento de Serviço do Azure.

O exemplo a seguir mostra um mínimo Program.cs para um projeto de host de aplicativo que configura um gatilho de fila. Neste exemplo, o gatilho de fila correspondente tem sua Connection propriedade definida como "MyQueueTriggerConnection".

var builder = DistributedApplication.CreateBuilder(args);

var myAppStorage = builder.AddAzureStorage("myAppStorage").RunAsEmulator();
var queues = myAppStorage.AddQueues("queues");

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithReference(queues, "MyQueueTriggerConnection");

builder.Build().Run();

Para outras integrações, chama para WithReference definir a configuração de uma forma diferente, disponibilizando-a para integrações de clientes Aspir, mas não para gatilhos e associações. Para essas integrações, você deve ligar WithEnvironment() para passar as informações de conexão para que o gatilho ou a ligação sejam resolvidos. O exemplo a seguir mostra como definir a variável de ambiente "MyBindingConnection" para um recurso que expõe uma expressão de cadeia de conexão:

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithEnvironment("MyBindingConnection", otherIntegration.Resource.ConnectionStringExpression);

Você pode configurar ambos WithReference() e WithEnvironment() se quiser que uma conexão seja usada tanto pelas integrações do cliente Aspire quanto pelo sistema de gatilhos e ligações.

Para alguns recursos, a estrutura de uma conexão pode ser diferente entre quando você a executa localmente e quando a publica no Azure. No exemplo anterior, otherIntegration poderia ser um recurso que é executado como um emulador, portanto ConnectionStringExpression , retornaria uma cadeia de conexão do emulador. No entanto, quando o recurso é publicado, o Aspire pode configurar uma ligação baseada em identidade e ConnectionStringExpression devolve o URI do serviço. Nesse caso, para configurar conexões baseadas em identidade para o Azure Functions, talvez seja necessário fornecer um nome de variável de ambiente diferente. O exemplo a seguir usa builder.ExecutionContext.IsPublishMode para adicionar condicionalmente o sufixo necessário:

builder.AddAzureFunctionsProject<Projects.MyFunctionsProject>("MyFunctionsProject")
    .WithEnvironment("MyBindingConnection" + (builder.ExecutionContext.IsPublishMode ? "__serviceUri" : ""), otherIntegration.Resource.ConnectionStringExpression);

Dependendo do cenário, também pode ser necessário ajustar as permissões que serão atribuídas para uma conexão baseada em identidade. Pode utilizar o método para personalizar a forma como o Aspire configura a infraestrutura quando publica o ConfigureConstruct<T>() seu projeto.

Consulte as páginas de referência de cada ligação para obter detalhes sobre os formatos de conexão suportados e as permissões que esses formatos exigem.

Depuração

Ao executar localmente usando o Visual Studio ou Visual Studio Code, você pode depurar seu projeto de trabalho isolado do .NET normalmente. No entanto, há dois cenários de depuração que não funcionam como esperado.

Depuração remota usando o 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 o Visual Studio, consulte Depuração remota.

Depuração ao direcionar o .NET Framework

Se seu projeto isolado tem como alvo o .NET Framework 4.8, você precisa executar etapas manuais para habilitar 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 antes de Main() 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 = new HostBuilder()
                .ConfigureFunctionsWorkerDefaults()
                .Build();

            host.Run();
        }
    }
}

Em seguida, você precisa anexar manualmente ao processo usando um depurador do .NET Framework. O Visual Studio ainda não faz isso automaticamente para aplicativos .NET Framework de processo de trabalho isolados, e a operação "Iniciar depuração" deve ser evitada.

No diretório do projeto (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 você pode usar o Visual Studio para anexar 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 anexado, a execução do processo será retomada e você poderá depurar.

Visualizar versões do .NET

Antes de uma versão geralmente disponível, uma versão do .NET pode ser lançada em um estado de visualização ou Go-live . Consulte a Política de Suporte Oficial do .NET para obter detalhes sobre esses estados.

Embora seja possível direcionar uma determinada versão de um projeto local do Functions, os aplicativos de função hospedados no Azure podem não ter essa versão disponível. O Azure Functions só pode ser usado com versões de visualização ou Go-live indicadas nesta seção.

Atualmente, o Azure Functions 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.

Usando um SDK .NET de visualização

Para usar o Azure Functions com uma versão de visualização do .NET, você precisa atualizar seu projeto da seguinte forma:

  1. Instalando a versão relevante do SDK do .NET em seu desenvolvimento
  2. Alterar a TargetFramework definição no ficheiro .csproj

Ao implantar em seu aplicativo de função no Azure, você também precisa garantir que a estrutura seja disponibilizada para o aplicativo. Durante o período de visualização, algumas ferramentas e experiências podem não apresentar a nova versão de visualização como uma opção. Se não vir a versão de pré-visualização incluída no portal do Azure, por exemplo, pode utilizar a API REST, os modelos Bicep ou a CLI do Azure para configurar a versão manualmente.

Para aplicativos hospedados no Windows, use o seguinte comando da CLI do Azure. 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 sobre o uso de versões de visualização do .NET

Tenha estas considerações em mente ao usar o Functions com versões de visualização do .NET:

  • Ao criar suas funções no Visual Studio, você deve usar o Visual Studio Preview, que dá suporte à criação de projetos do Azure Functions com SDKs de visualização do .NET.

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

    1. Navegue até Opções de Ferramentas>, escolha Azure Functions em Projetos e Soluções.
    2. Selecione Verificar se há atualizações e instale as atualizações conforme solicitado.
  • Durante um período de visualização, seu ambiente de desenvolvimento pode ter uma versão mais recente do .NET preview do que o serviço hospedado. 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 e anote a versão de visualização que você está usando atualmente durante o dotnet --list-sdks 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-8.0.100-preview.7.23376.3 --force faz com que o sistema use o SDK do .NET 8 Preview 7 ao criar seu projeto.

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