管理 Azure Functions 中的连接

函数应用中的函数共享资源。 这些共享的资源包括连接:HTTP 连接、数据库连接以及到 Azure 存储之类服务的连接。 当许多函数在消耗函数中同时运行时,可能会耗尽可用的连接。 本文介绍如何编写函数,避免使用超出需要的连接数。

注意

本文描述的连接限制仅在消耗计划中运行时适用。 但是,在任何计划中运行时,此处介绍的技术可能都是有益的。

连接限制

消耗计划中的可用连接数有限,因为此计划中的函数应用在沙盒环境中运行。 沙盒对代码施加的限制之一是对出站连接数量进行限制,目前每个实例的活动连接数上限为 600 个(总共 1,200 个连接)。 达到此限制时,函数运行时会将以下消息写入日志:Host thresholds exceeded: Connections。 有关详细信息,请参阅 Functions 服务限制

此限制是按实例施加的。 缩放控制器添加函数应用实例以处理更多请求时,每个实例都有单独的连接限制。 这意味着没有全局连接限制,你可以跨所有活动实例建立比 600 个活动连接多得多的连接。

进行故障排除时,请确保已为函数应用启用 Application Insights。 借助 Application Insights,你可以查看函数应用的指标,如执行。 有关详细信息,请参阅在 Application Insights 中查看遥测

静态客户端

为了避免占用的连接数超过实际所需,可重复使用客户端实例,而不是在每次调用函数时创建新的实例。 不管编写函数时使用什么语言,建议重复使用客户端连接。 例如,如果使用单个静态客户端,HttpClientDocumentClient 和 Azure 存储客户端等 .NET 客户端可以管理连接。

在 Azure Functions 应用程序中使用特定于服务的客户端时,请遵循以下准则:

  • 不要在每次调用函数时创建新的客户端。
  • 应创建一个可在每次调用函数时使用的静态客户端。
  • 如果不同的函数使用相同的服务,请考虑在共享帮助程序类中创建单个静态客户端。

客户端代码示例

本部分演示了用于通过函数代码创建和使用客户端的最佳做法。

HTTP 请求

下面是用于创建静态 HttpClient 实例的 C# 函数代码示例:

// 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
}

关于 .NET 中 HttpClient 的一个常见问题是“我应该释放我的客户端吗?”通常在使用完实现 IDisposable 的对象后将其释放。 但是,你不会释放静态客户端,因为在函数结束后还需要使用它。 你需要将静态客户端一直保留到应用程序生存期结束。

Azure Cosmos DB 客户端

CosmosClient 连接到 Azure Cosmos DB 实例。 Azure Cosmos DB 文档建议在应用程序生存期内使用单一实例 Azure Cosmos DB 客户端。 以下示例展示了在函数中执行该操作的一种模式:

#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.cn: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
}

同时,为触发器创建一个名为“function.proj”的文件,并添加以下内容:


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

SqlClient 连接

函数代码可使用 SQL Server 的 .NET Framework 数据提供程序 (SqlClient) 连接到 SQL 关系数据库。 这也是依赖于 ADO.NET 的数据框架(例如实体框架)的基础提供程序。 与 HttpClientDocumentClient 连接不同,ADO.NET 默认实现连接池。 但是,由于连接仍可能耗尽,因此应优化数据库连接。 有关详细信息,请参阅 SQL Server 连接池 (ADO.NET)

提示

某些数据框架(例如实体框架)通常从配置文件的 ConnectionStrings 节获取连接字符串。 在这种情况下,必须将 SQL 数据库连接字符串显式添加到函数应用设置的连接字符串集合以及本地项目中的 local.settings.json 文件。 如果要在函数代码中创建 SqlConnection 的实例,则应将连接字符串值与其他连接一起存储在应用程序设置中

后续步骤

有关更多 Azure Functions 性能提示,请参阅优化 Azure Functions 的性能和可靠性