Gerir ligações nas Funções do AzureManage connections in Azure Functions

As funções numa aplicação de função partilham recursos.Functions in a function app share resources. Entre esses recursos partilhados encontram-se ligações: conexões HTTP, ligações de base de dados e ligações a serviços como o Azure Storage.Among those shared resources are connections: HTTP connections, database connections, and connections to services such as Azure Storage. Quando muitas funções estão a funcionar simultaneamente, é possível ficar sem ligações disponíveis.When many functions are running concurrently, it's possible to run out of available connections. Este artigo explica como codificar as suas funções para evitar a utilização de mais ligações do que as necessárias.This article explains how to code your functions to avoid using more connections than they need.

Limite de ligaçõesConnection limit

O número de ligações disponíveis é limitado em parte porque uma aplicação de função funciona num ambiente de caixa de areia.The number of available connections is limited partly because a function app runs in a sandbox environment. Uma das restrições que a caixa de areia impõe no seu código é um limite para o número de ligações de saída, que atualmente é de 600 ligações ativas (1.200 no total) por exemplo.One of the restrictions that the sandbox imposes on your code is a limit on the number of outbound connections, which is currently 600 active (1,200 total) connections per instance. Quando se atinge este limite, o tempo de execução das funções escreve a seguinte mensagem para os registos: Host thresholds exceeded: Connections .When you reach this limit, the functions runtime writes the following message to the logs: Host thresholds exceeded: Connections. Para mais informações, consulte os limites de serviço funções.For more information, see the Functions service limits.

Este limite é por exemplo.This limit is per instance. Quando o controlador de escala adiciona instâncias de aplicação de função para lidar com mais pedidos, cada instância tem um limite de ligação independente.When the scale controller adds function app instances to handle more requests, each instance has an independent connection limit. Isso significa que não há limite de ligação global, e você pode ter muito mais de 600 conexões ativas em todos os casos ativos.That means there's no global connection limit, and you can have much more than 600 active connections across all active instances.

Ao resolver problemas, certifique-se de que ativou o Application Insights para a sua aplicação de função.When troubleshooting, make sure that you have enabled Application Insights for your function app. O Application Insights permite-lhe visualizar métricas para as suas aplicações de função como execuções.Application Insights lets you view metrics for your function apps like executions. Para obter mais informações, consulte a telemetria em Insights de Aplicação.For more information, see View telemetry in Application Insights.

Clientes estáticosStatic clients

Para evitar mais ligações do que o necessário, reutilizar as instâncias do cliente em vez de criar novas com cada invocação de função.To avoid holding more connections than necessary, reuse client instances rather than creating new ones with each function invocation. Recomendamos a reutilização das ligações do cliente para qualquer idioma em que possa escrever a sua função.We recommend reusing client connections for any language that you might write your function in. Por exemplo, clientes .NET como os clientes HttpClient, DocumentCliente Azure Storage podem gerir ligações se utilizar um único cliente estático.For example, .NET clients like the HttpClient, DocumentClient, and Azure Storage clients can manage connections if you use a single, static client.

Aqui estão algumas diretrizes a seguir quando estiver a utilizar um cliente específico de serviço numa aplicação Azure Functions:Here are some guidelines to follow when you're using a service-specific client in an Azure Functions application:

  • Não crie um novo cliente com todas as funções invocando.Do not create a new client with every function invocation.
  • Crie um único cliente estático que cada invocação de funções pode usar.Do create a single, static client that every function invocation can use.
  • Considere criar um cliente único e estático numa classe de ajudante partilhada se diferentes funções usarem o mesmo serviço.Consider creating a single, static client in a shared helper class if different functions use the same service.

Exemplos de código do clienteClient code examples

Esta secção demonstra as melhores práticas para criar e utilizar clientes a partir do seu código de função.This section demonstrates best practices for creating and using clients from your function code.

Exemplo httpClient (C#)HttpClient example (C#)

Aqui está um exemplo do código de função C# que cria uma instância estática httpClient:Here's an example of C# function code that creates a static HttpClient instance:

// Create a single, static HttpClient
private static HttpClient httpClient = new HttpClient();

public static async Task Run(string input)
{
    var response = await httpClient.GetAsync("https://example.com");
    // Rest of function
}

Uma pergunta comum sobre httpClient em .NET é "Devo dispor do meu cliente?"A common question about HttpClient in .NET is "Should I dispose of my client?" Em geral, deita-se fora os objetos que implementam IDisposable quando termina a sua utilização.In general, you dispose of objects that implement IDisposable when you're done using them. Mas não se descarta um cliente estático porque não se acaba de usá-lo quando a função termina.But you don't dispose of a static client because you aren't done using it when the function ends. Quer que o cliente estático viva durante a sua inscrição.You want the static client to live for the duration of your application.

Exemplos de agentes HTTP (JavaScript)HTTP agent examples (JavaScript)

Como fornece melhores opções de gestão de ligação, deve utilizar a classe nativa http.agent em vez de métodos não nativos, como o node-fetch módulo.Because it provides better connection management options, you should use the native http.agent class instead of non-native methods, such as the node-fetch module. Os parâmetros de ligação são configurados através de opções na http.agent classe.Connection parameters are configured through options on the http.agent class. Para opções detalhadas disponíveis com o agente HTTP, consulte novo Agente( [ ] opções).For detailed options available with the HTTP agent, see new Agent([options]).

A classe global http.globalAgent utilizada tem todos estes http.request() valores definidos para os respetivos incumprimentos.The global http.globalAgent class used by http.request() has all of these values set to their respective defaults. A forma recomendada de configurar os limites de ligação em Funções é definir um número máximo a nível global.The recommended way to configure connection limits in Functions is to set a maximum number globally. O exemplo a seguir define o número máximo de tomadas para a aplicação de função:The following example sets the maximum number of sockets for the function app:

http.globalAgent.maxSockets = 200;

O exemplo a seguir cria um novo pedido HTTP com um agente HTTP personalizado apenas para esse pedido:The following example creates a new HTTP request with a custom HTTP agent only for that request:

var http = require('http');
var httpAgent = new http.Agent();
httpAgent.maxSockets = 200;
options.agent = httpAgent;
http.request(options, onResponseCallback);

Exemplo de código documentclient (C#)DocumentClient code example (C#)

DocumentClient conecta-se a uma instância DB Azure Cosmos.DocumentClient connects to an Azure Cosmos DB instance. A documentação da Azure Cosmos DB recomenda que utilize um cliente singleton Azure Cosmos DB para o tempo de vida da sua aplicação.The Azure Cosmos DB documentation recommends that you use a singleton Azure Cosmos DB client for the lifetime of your application. O exemplo a seguir mostra um padrão para fazer isso numa função:The following example shows one pattern for doing that in a function:

#r "Microsoft.Azure.Documents.Client"
using Microsoft.Azure.Documents.Client;

private static Lazy<DocumentClient> lazyClient = new Lazy<DocumentClient>(InitializeDocumentClient);
private static DocumentClient documentClient => lazyClient.Value;

private static DocumentClient InitializeDocumentClient()
{
    // Perform any initialization here
    var uri = new Uri("example");
    var authKey = "authKey";
    
    return new DocumentClient(uri, authKey);
}

public static async Task Run(string input)
{
    Uri collectionUri = UriFactory.CreateDocumentCollectionUri("database", "collection");
    object document = new { Data = "example" };
    await documentClient.UpsertDocumentAsync(collectionUri, document);
    
    // Rest of function
}

Se estiver a trabalhar com funções v3.x, precisa de uma referência a Microsoft.Azure.DocumentDB.Core.If you are working with functions v3.x, you need a reference to Microsoft.Azure.DocumentDB.Core. Adicione uma referência no código:Add a reference in the code:

#r "Microsoft.Azure.DocumentDB.Core"

Além disso, crie um ficheiro chamado "function.proj" para o seu gatilho e adicione o conteúdo abaixo:Also, create a file named "function.proj" for your trigger and add the below content :


<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>netcoreapp3.0</TargetFramework>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="Microsoft.Azure.DocumentDB.Core" Version="2.12.0" />
    </ItemGroup>
</Project>

Exemplo de código CosmosClient (JavaScript)CosmosClient code example (JavaScript)

CosmosClient conecta-se a um exemplo de Azure Cosmos DB.CosmosClient connects to an Azure Cosmos DB instance. A documentação da Azure Cosmos DB recomenda que utilize um cliente singleton Azure Cosmos DB para o tempo de vida da sua aplicação.The Azure Cosmos DB documentation recommends that you use a singleton Azure Cosmos DB client for the lifetime of your application. O exemplo a seguir mostra um padrão para fazer isso numa função:The following example shows one pattern for doing that in a function:

const cosmos = require('@azure/cosmos');
const endpoint = process.env.COSMOS_API_URL;
const key = process.env.COSMOS_API_KEY;
const { CosmosClient } = cosmos;

const client = new CosmosClient({ endpoint, key });
// All function invocations also reference the same database and container.
const container = client.database("MyDatabaseName").container("MyContainerName");

module.exports = async function (context) {
    const { resources: itemArray } = await container.items.readAll().fetchAll();
    context.log(itemArray);
}

Ligações SqlClientSqlClient connections

O seu código de função pode utilizar o Fornecedor de Dados De Quadro .NET para o SQL Server(SqlClient)para fazer ligações a uma base de dados relacional SQL.Your function code can use the .NET Framework Data Provider for SQL Server (SqlClient) to make connections to a SQL relational database. Este é também o fornecedor subjacente aos quadros de dados que dependem de ADO.NET, como o Quadro de Entidades.This is also the underlying provider for data frameworks that rely on ADO.NET, such as Entity Framework. Ao contrário das ligações HttpClient e DocumentClient, ADO.NET implementa a ligação por padrão.Unlike HttpClient and DocumentClient connections, ADO.NET implements connection pooling by default. Mas como ainda pode ficar sem ligações, deve otimizar as ligações à base de dados.But because you can still run out of connections, you should optimize connections to the database. Para obter mais informações, consulte o SqL Server Connection Pooling (ADO.NET).For more information, see SQL Server Connection Pooling (ADO.NET).

Dica

Alguns quadros de dados, tais como o Entity Framework, obtêm tipicamente cadeias de ligação a partir da secção ConnectionStrings de um ficheiro de configuração.Some data frameworks, such as Entity Framework, typically get connection strings from the ConnectionStrings section of a configuration file. Neste caso, deve adicionar explicitamente as cadeias de ligação à base de dados SQL à recolha de cordas de ligação das definições da aplicação de funções e nolocal.settings.jsem ficheiro no seu projeto local.In this case, you must explicitly add SQL database connection strings to the Connection strings collection of your function app settings and in the local.settings.json file in your local project. Se estiver a criar uma instância de SqlConnection no seu código de função, deverá armazenar o valor da cadeia de ligação nas definições de Aplicação com as suas outras ligações.If you're creating an instance of SqlConnection in your function code, you should store the connection string value in Application settings with your other connections.

Passos seguintesNext steps

Para obter mais informações sobre o porquê de recomendarmos clientes estáticos, consulte anti-artigo de instantâneo impróprio.For more information about why we recommend static clients, see Improper instantiation antipattern.

Para obter mais dicas de desempenho do Azure Functions, consulte Otimizar o desempenho e a fiabilidade das Funções Azure.For more Azure Functions performance tips, see Optimize the performance and reliability of Azure Functions.