Administración de conexiones en Azure Functions

Las funciones dentro de una aplicación de función comparten recursos. 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. Cuando se ejecutan simultáneamente muchas funciones en un plan de consumo, es posible que se agoten las conexiones disponibles. Este artículo explica cómo codificar las funciones para evitar el uso de más conexiones que las que se necesitan.

Nota

Los límites de conexión descritos en este artículo solo se aplican cuando se ejecutan en un plan de consumo. Sin embargo, las técnicas que se describen aquí pueden ser beneficiosas cuando se ejecutan en cualquier plan.

Límite de conexiones

El número de conexiones disponibles de un plan de consumo está limitado en parte porque una aplicación de funciones de este plan se ejecuta en un entorno de espacio aislado. 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. 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. Para obtener más información, consulte Límites de servicio en Functions.

Este límite es por instancia. 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. 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.

Para solucionar el problema, asegúrese de que ha habilitado Application Insights para su aplicación de funciones. Application Insights permite ver las métricas de las aplicaciones de funciones, como las ejecuciones. Para obtener más información, consulte Visualización de la telemetría en Application Insights.

Clientes estáticos

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. Se recomienda la reutilización de las conexiones de cliente para cualquier lenguaje en el que haya escrito su función. 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.

Estas son algunas directrices que se deben seguir al utilizar a un cliente específico del servicio en una aplicación de Azure Functions:

  • No cree un nuevo cliente con cada invocación de función.
  • Cree un único cliente estático que pueda ser utilizado por cada invocación de función.
  • Considere la posibilidad de crear un cliente único y estático en una clase auxiliar compartida si funciones diferentes utilizan el mismo servicio.

Ejemplos de código de cliente

En esta sección se muestran los procedimientos recomendados para crear y utilizar clientes a partir del código de función.

Solicitudes HTTP

Este es un ejemplo de código de función de C# que crea una instancia de HttpClient estática:

// 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 en .NET es "¿Debo eliminar mi cliente?" En general, debe desechar los objetos que implementan IDisposable cuando haya terminado de usarlos. Pero no se desecha un cliente estático porque su uso no ha terminado cuando finaliza la función. Desea que el cliente estático viva en toda la duración de la aplicación.

Clientes de Azure Cosmos DB

CosmosClient se conecta a una instancia de Azure Cosmos DB. 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. En el ejemplo siguiente se muestra un patrón para realizarlo en una función:

#r "Microsoft.Azure.Cosmos"
using Microsoft.Azure.Cosmos;

private static Lazy<CosmosClient> lazyClient = new Lazy<CosmosClient>(InitializeCosmosClient);
private static CosmosClient cosmosClient => lazyClient.Value;

private static CosmosClient InitializeCosmosClient()
{
    // Perform any initialization here
    var uri = "https://youraccount.documents.azure.com:443";
    var authKey = "authKey";
   
    return new CosmosClient(uri, authKey);
}

public static async Task Run(string input)
{
    Container container = cosmosClient.GetContainer("database", "collection");
    MyItem item = new MyItem{ id = "myId", partitionKey = "myPartitionKey", data = "example" };
    await container.UpsertItemAsync(document);
   
    // Rest of function
}

Además, cree un archivo denominado "function.proj" para el desencadenador y agregue el contenido siguiente:


<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>netcoreapp3.1</TargetFramework>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="Microsoft.Azure.Cosmos" Version="3.23.0" />
    </ItemGroup>
</Project>

Conexiones de SqlClient

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. También es el proveedor subyacente para los marcos de datos que se basan en ADO.NET, como Entity Framework. A diferencia de las conexiones de HttpClient y DocumentClient, ADO.NET implementa la agrupación de conexiones de manera predeterminada. Sin embargo, como todavía puede quedarse sin conexiones, debería optimizar las conexiones con la base de datos. Para más información, consulte el artículo sobre la agrupación de conexiones de SQL Server (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. 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. 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.

Pasos siguientes

Para obtener más información sobre por qué se recomiendan clientes estáticos, consulte Antipatrón Improper Instantiation.

Para más sugerencias de rendimiento de Azure Functions, consulte Optimización del rendimiento y la confiabilidad de Azure Functions.