Administración de conexiones en Azure FunctionsManage connections in Azure Functions

Las funciones dentro de una aplicación de función comparten recursos.Functions in a function app share resources. Entre esos recursos compartidos se encuentran las conexiones: Las conexiones HTTP, las conexiones de base de datos y las conexiones a servicios como Azure Storage.Among those shared resources are connections: HTTP connections, database connections, and connections to services such as Azure Storage. Cuando se ejecutan simultáneamente muchas funciones es posible que se agoten las conexiones disponibles.When many functions are running concurrently, it's possible to run out of available connections. Este artículo explica cómo codificar las funciones para evitar el uso de más conexiones que las que se necesitan.This article explains how to code your functions to avoid using more connections than they need.

Límite de conexionesConnection limit

El número de conexiones disponibles está limitado en parte porque una aplicación de función se ejecuta en un entorno de espacio aislado.The number of available connections is limited partly because a function app runs in a sandbox environment. Una de las restricciones que impone el espacio aislado en el código es un límite en el número de conexiones salientes, que actualmente es 600 (de total de 1200) conexiones activas por instancia.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. Cuando se alcanza este límite, el entorno de ejecución de las funciones crea un registro con el siguiente mensaje: Host thresholds exceeded: Connections.When you reach this limit, the functions runtime writes the following message to the logs: Host thresholds exceeded: Connections. Para obtener más información, consulte Límites de servicio en Functions.For more information, see the Functions service limits.

Este límite es por instancia.This limit is per instance. Cuando el controlador de escala agrega instancias de aplicación de función para controlar más solicitudes, cada instancia tendrá un límite de conexión independiente.When the scale controller adds function app instances to handle more requests, each instance has an independent connection limit. Esto significa que no hay ningún límite de conexión global y puede tener mucho más de 600 conexiones activas de todas las instancias activas.That means there's no global connection limit, and you can have much more than 600 active connections across all active instances.

Para solucionar el problema, asegúrese de que ha habilitado Application Insights para su aplicación de funciones.When troubleshooting, make sure that you have enabled Application Insights for your function app. Application Insights permite ver las métricas de las aplicaciones de funciones, como las ejecuciones.Application Insights lets you view metrics for your function apps like executions. Para obtener más información, consulte Visualización de la telemetría en Application Insights.For more information, see View telemetry in Application Insights.

Clientes estáticosStatic clients

Para evitar mantener más conexiones de las necesarias, reutilice las instancias de cliente en lugar de crear nuevas con cada invocación de función.To avoid holding more connections than necessary, reuse client instances rather than creating new ones with each function invocation. Se recomienda la reutilización de las conexiones de cliente para cualquier lenguaje en el que haya escrito su función.We recommend reusing client connections for any language that you might write your function in. Por ejemplo, los cclientes de .NET, como HttpClient, DocumentClient y los clientes de Azure Storage, pueden administrar las conexiones si usa un cliente único y estático.For example, .NET clients like the HttpClient, DocumentClient, and Azure Storage clients can manage connections if you use a single, static client.

Estas son algunas directrices que se deben seguir al utilizar a un cliente específico del servicio en una aplicación de Azure Functions:Here are some guidelines to follow when you're using a service-specific client in an Azure Functions application:

  • No cree un nuevo cliente con cada invocación de función.Do not create a new client with every function invocation.
  • Cree un único cliente estático que pueda ser utilizado por cada invocación de función.Do create a single, static client that every function invocation can use.
  • Considere la posibilidad de crear un cliente único y estático en una clase auxiliar compartida si funciones diferentes utilizan el mismo servicio.Consider creating a single, static client in a shared helper class if different functions use the same service.

Ejemplos de código de clienteClient code examples

En esta sección se muestran los procedimientos recomendados para crear y utilizar clientes a partir del código de función.This section demonstrates best practices for creating and using clients from your function code.

Ejemplo de HttpClient (C#)HttpClient example (C#)

Este es un ejemplo de código de función de C# que crea una instancia de HttpClient estática: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
}

Una pregunta común sobre HttpClient de .NET es "¿Debería desechar mi cliente?"A common question about HttpClient in .NET is "Should I dispose of my client?" En general, se desechan los objetos que implementan IDisposable cuando se ha terminado de utilizarlos.In general, you dispose of objects that implement IDisposable when you're done using them. Pero no se desecha un cliente estático porque su uso no ha terminado cuando finaliza la función.But you don't dispose of a static client because you aren't done using it when the function ends. Desea que el cliente estático viva en toda la duración de la aplicación.You want the static client to live for the duration of your application.

Ejemplos de agente HTTP (JavaScript)HTTP agent examples (JavaScript)

Debido a que proporciona mejores opciones de administración de conexiones, debería utilizar la clase nativa http.agent en lugar de los métodos no nativos, como el módulo node-fetch.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. Los parámetros de conexión se configuran mediante las opciones de la clase http.agent.Connection parameters are configured through options on the http.agent class. Consulte new Agent([options]) para ver las opciones detalladas disponibles con el agente HTTP.For detailed options available with the HTTP agent, see new Agent([options]).

La clase http.globalAgent global que se utiliza en http.request() tiene todos estos valores establecidos a sus respectivos valores predeterminados.The global http.globalAgent class used by http.request() has all of these values set to their respective defaults. La forma recomendada de configurar los límites de conexión en Functions es establecer un número máximo globalmente.The recommended way to configure connection limits in Functions is to set a maximum number globally. El siguiente ejemplo establece el número máximo de sockets para la aplicación de función:The following example sets the maximum number of sockets for the function app:

http.globalAgent.maxSockets = 200;

En el ejemplo siguiente se crea una nueva solicitud HTTP con un agente HTTP personalizado solo para esa solicitud: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);

Ejemplo de código de DocumentClient (C#)DocumentClient code example (C#)

DocumentClient se conecta a una instancia de Azure Cosmos DB.DocumentClient connects to an Azure Cosmos DB instance. La documentación de Azure Cosmos DB recomienda el uso de un cliente de Azure Cosmos DB singleton para el ciclo de vida de la aplicación.The Azure Cosmos DB documentation recommends that you use a singleton Azure Cosmos DB client for the lifetime of your application. En el ejemplo siguiente se muestra un patrón para realizarlo en una función: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
}

Si está trabajando con funciones v3.x, necesita una referencia a Microsoft.Azure.DocumentDB.Core.If you are working with functions v3.x, you need a reference to Microsoft.Azure.DocumentDB.Core. Agregar una referencia en el código:Add a reference in the code:

#r "Microsoft.Azure.DocumentDB.Core"

Además, cree un archivo denominado "function.proj" para el desencadenador y agregue el contenido siguiente: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>

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

CosmosClient se conecta a una instancia de Azure Cosmos DB.CosmosClient connects to an Azure Cosmos DB instance. La documentación de Azure Cosmos DB recomienda el uso de un cliente de Azure Cosmos DB singleton para el ciclo de vida de la aplicación.The Azure Cosmos DB documentation recommends that you use a singleton Azure Cosmos DB client for the lifetime of your application. En el ejemplo siguiente se muestra un patrón para realizarlo en una función: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);
}

Conexiones de SqlClientSqlClient connections

El código de la función puede usar el proveedor de datos .NET Framework para SQL Server (SqlClient) para establecer conexiones con una base de datos relacional de SQL.Your function code can use the .NET Framework Data Provider for SQL Server (SqlClient) to make connections to a SQL relational database. También es el proveedor subyacente para los marcos de datos que se basan en ADO.NET, como Entity Framework.This is also the underlying provider for data frameworks that rely on ADO.NET, such as Entity Framework. A diferencia de las conexiones de HttpClient y DocumentClient, ADO.NET implementa la agrupación de conexiones de manera predeterminada.Unlike HttpClient and DocumentClient connections, ADO.NET implements connection pooling by default. Sin embargo, como todavía puede quedarse sin conexiones, debería optimizar las conexiones con la base de datos.But because you can still run out of connections, you should optimize connections to the database. Para más información, consulte el artículo sobre la agrupación de conexiones de SQL Server (ADO.NET).For more information, see SQL Server Connection Pooling (ADO.NET).

Sugerencia

Algunos marcos de datos, como Entity Framework, habitualmente obtienen cadenas de conexión desde la sección ConnectionStrings de un archivo de configuración.Some data frameworks, such as Entity Framework, typically get connection strings from the ConnectionStrings section of a configuration file. En este caso, debe agregar explícitamente las cadenas de conexión de base de datos SQL a la colección Cadenas de conexión de la configuración de la aplicación de función y en el archivo local.settings.json del proyecto 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. Si está creando una instancia de SqlConnection en el código de la función, debe almacenar el valor de la cadena de conexión en Configuración de la aplicación con las otras conexiones.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.

Pasos siguientesNext steps

Para obtener más información sobre por qué se recomiendan clientes estáticos, consulte Antipatrón Improper Instantiation.For more information about why we recommend static clients, see Improper instantiation antipattern.

Para más sugerencias de rendimiento de Azure Functions, consulte Optimización del rendimiento y la confiabilidad de Azure Functions.For more Azure Functions performance tips, see Optimize the performance and reliability of Azure Functions.