函数应用中的函数共享资源。 在这些共享资源中包括连接:HTTP 连接、数据库连接和与服务(如Azure 存储)的连接。 当许多函数在Consumption计划中同时运行时,可能会耗尽可用的连接。 本文介绍如何编写函数,避免使用超出需要的连接数。
注意
本文描述的连接限制仅在消耗计划中运行时适用。 然而,无论使用何种方案,此处描述的技术可能都会带来好处。
连接限制
消耗计划中可用的连接数有限,部分原因是此计划中的函数应用在 sandbox 环境中运行。 沙盒对代码施加的限制之一是对出站连接数量进行限制,目前每个实例的活动连接数上限为 600 个(总共 1,200 个连接)。 达到此限制时,函数运行时会将以下消息写入日志:Host thresholds exceeded: Connections。 有关详细信息,请参阅 Functions 服务限制。
此限制适用于每个实例。 缩放控制器添加函数应用实例以处理更多请求时,每个实例都有单独的连接限制。 这意味着没有全局连接限制,你可以跨所有活动实例建立比 600 个活动连接多得多的连接。
进行故障排除时,请确保已为函数应用启用 Application Insights。 借助 Application Insights,你可以查看函数应用的指标,如执行。 有关详细信息,请参阅在 Application Insights 中查看遥测。
静态客户端
为了避免占用的连接数超过实际所需,可重复使用客户端实例,而不是在每次调用函数时创建新的实例。 不管编写函数时使用什么语言,建议重复使用客户端连接。 例如,.NET客户端(如 HttpClient、DocumentClient,Azure 存储客户端在使用单个静态客户端时可以管理连接。
下面是在 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 连接实例
函数代码可以使用 .NET Framework 数据提供程序(SqlClient)来连接到 SQL 关系数据库。 这也是依赖于 ADO.NET 的数据框架的基础提供程序,例如 Entity Framework。 与 HttpClient 和 DocumentClient 连接不同,ADO.NET默认实现连接池。 但是,由于连接仍可能耗尽,因此应优化数据库连接。 有关详细信息,请参阅 SQL Server 连接池(ADO.NET)。
提示
某些数据框架(例如实体框架)通常从配置文件的 ConnectionStrings 节获取连接字符串。 在这种情况下,必须将 SQL 数据库连接字符串显式添加到函数应用设置的连接字符串集合以及本地项目中的 local.settings.json 文件中。 如果要在函数代码中创建 SqlConnection 实例,则应将连接字符串值与其他连接一起存储在 应用设置中。
后续步骤
有关更多 Azure Functions 性能提示,请参阅 优化 Azure Functions 的性能和可靠性。