您现在访问的是微软AZURE全球版技术文档网站,若需要访问由世纪互联运营的MICROSOFT AZURE中国区技术文档网站,请访问 https://docs.azure.cn.

管理 Azure Functions 中的连接Manage connections in Azure Functions

函数应用中的函数共享资源。Functions in a function app share resources. 这些共享的资源包括连接:HTTP 连接、数据库连接以及到 Azure 存储之类服务的连接。Among those shared resources are connections: HTTP connections, database connections, and connections to services such as Azure Storage. 当许多函数同时运行时,可能会耗尽可用的连接。When many functions are running concurrently, it's possible to run out of available connections. 本文介绍如何编写函数,避免使用超出需要的连接数。This article explains how to code your functions to avoid using more connections than they need.

连接限制Connection limit

可用连接数量受到限制,部分原因是函数应用在沙盒环境中运行。The number of available connections is limited partly because a function app runs in a sandbox environment. 沙盒对代码施加的限制之一是对出站连接数量进行限制,目前每个实例的活动连接数上限为 600 个(总共 1,200 个连接)。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. 达到此限制时,函数运行时会将以下消息写入日志:Host thresholds exceeded: ConnectionsWhen you reach this limit, the functions runtime writes the following message to the logs: Host thresholds exceeded: Connections. 有关详细信息,请参阅 Functions 服务限制For more information, see the Functions service limits.

此限制是按实例施加的。This limit is per instance. 缩放控制器添加函数应用实例以处理更多请求时,每个实例都有单独的连接限制。When the scale controller adds function app instances to handle more requests, each instance has an independent connection limit. 这意味着没有全局连接限制,你可以跨所有活动实例建立比 600 个活动连接多得多的连接。That means there's no global connection limit, and you can have much more than 600 active connections across all active instances.

进行故障排除时, 请确保已启用函数应用 Application Insights。When troubleshooting, make sure that you have enabled Application Insights for your function app. Application Insights 使你可以查看函数应用的指标, 如执行。Application Insights lets you view metrics for your function apps like executions. 有关详细信息, 请参阅在 Application Insights 中查看遥测For more information, see View telemetry in Application Insights.

静态客户端Static clients

为了避免占用的连接数超过实际所需,可重复使用客户端实例,而不是在每次调用函数时创建新的实例。To avoid holding more connections than necessary, reuse client instances rather than creating new ones with each function invocation. 不管编写函数时使用什么语言,建议重复使用客户端连接。We recommend reusing client connections for any language that you might write your function in. 例如,如果使用单个静态客户端,HttpClientDocumentClient 和 Azure 存储客户端等 .NET 客户端可以管理连接。For example, .NET clients like the HttpClient, DocumentClient, and Azure Storage clients can manage connections if you use a single, static client.

在 Azure Functions 应用程序中使用特定于服务的客户端时,请遵循以下准则:Here are some guidelines to follow when you're using a service-specific client in an Azure Functions application:

  • 不要在每次调用函数时创建新的客户端。Do not create a new client with every function invocation.
  • 应创建一个可在每次调用函数时使用的静态客户端。Do create a single, static client that every function invocation can use.
  • 如果不同的函数使用相同的服务,请考虑在共享帮助程序类中创建单个静态客户端。Consider creating a single, static client in a shared helper class if different functions use the same service.

客户端代码示例Client code examples

本部分演示了用于通过函数代码创建和使用客户端的最佳做法。This section demonstrates best practices for creating and using clients from your function code.

HttpClient 示例 (C#)HttpClient example (C#)

下面是用于创建静态 HttpClient 实例的 C# 函数代码示例: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
}

关于 .NET 中的 HttpClient 的一个常见问题是“我应该释放我的客户端吗?”A common question about HttpClient in .NET is "Should I dispose of my client?" 一般情况下,在使用对象实现了 IDisposable 之后,你会释放这些对象。In general, you dispose of objects that implement IDisposable when you're done using them. 但是,你不会释放静态客户端,因为在函数结束后还需要使用它。But you don't dispose of a static client because you aren't done using it when the function ends. 你需要将静态客户端一直保留到应用程序生存期结束。You want the static client to live for the duration of your application.

HTTP 代理示例 (JavaScript)HTTP agent examples (JavaScript)

因为它提供了更好的连接管理选项,所以你应当使用本机 http.agent 类而不应当使用非本机方法,例如 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. 连接参数通过 http.agent 类上的选项配置。Connection parameters are configured through options on the http.agent class. 有关 HTTP 代理的可用详细选项,请参阅 new Agent([options])For detailed options available with the HTTP agent, see new Agent([options]).

http.request() 使用的全局 http.globalAgent 类将这些值全部设置为各自的默认值。The global http.globalAgent class used by http.request() has all of these values set to their respective defaults. 在 Functions 中配置连接限制的建议方法是全局设置一个最大数量。The recommended way to configure connection limits in Functions is to set a maximum number globally. 以下示例为函数应用设置最大 socket 数量:The following example sets the maximum number of sockets for the function app:

http.globalAgent.maxSockets = 200;

以下示例创建一个新的 HTTP 请求,并采用仅用于该请求的自定义 HTTP 代理: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);

DocumentClient 代码示例 (C#)DocumentClient code example (C#)

DocumentClient 连接到 Azure Cosmos DB 实例。DocumentClient connects to an Azure Cosmos DB instance. Azure Cosmos DB 文档建议在应用程序生存期内使用单一实例 Azure Cosmos DB 客户端The Azure Cosmos DB documentation recommends that you use a singleton Azure Cosmos DB client for the lifetime of your application. 以下示例展示了在函数中执行该操作的一种模式: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
}

CosmosClient 代码示例 (JavaScript)CosmosClient code example (JavaScript)

CosmosClient 连接到 Azure Cosmos DB 实例。CosmosClient connects to an Azure Cosmos DB instance. Azure Cosmos DB 文档建议在应用程序生存期内使用单一实例 Azure Cosmos DB 客户端The Azure Cosmos DB documentation recommends that you use a singleton Azure Cosmos DB client for the lifetime of your application. 以下示例展示了在函数中执行该操作的一种模式: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);
}

SqlClient 连接SqlClient connections

函数代码可使用 SQL Server 的 .NET Framework 数据提供程序 (SqlClient) 连接到 SQL 关系数据库。Your function code can use the .NET Framework Data Provider for SQL Server (SqlClient) to make connections to a SQL relational database. 这也是依赖于 ADO.NET 的数据框架(例如实体框架)的基础提供程序。This is also the underlying provider for data frameworks that rely on ADO.NET, such as Entity Framework. HttpClientDocumentClient 连接不同,ADO.NET 默认实现连接池。Unlike HttpClient and DocumentClient connections, ADO.NET implements connection pooling by default. 但是,由于连接仍可能耗尽,因此应优化数据库连接。But because you can still run out of connections, you should optimize connections to the database. 有关详细信息,请参阅 SQL Server 连接池 (ADO.NET)For more information, see SQL Server Connection Pooling (ADO.NET).

提示

某些数据框架(例如实体框架)通常从配置文件的 ConnectionStrings 节获取连接字符串。Some data frameworks, such as Entity Framework, typically get connection strings from the ConnectionStrings section of a configuration file. 在这种情况下,必须将 SQL 数据库连接字符串显式添加到函数应用设置的连接字符串集合以及本地项目中的 local.settings.json 文件中。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. 如果要在函数代码中创建 SqlConnection 的实例,则应将连接字符串值与其他连接一起存储在应用程序设置中。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.

后续步骤Next steps

有关为何建议静态客户端的详细信息, 请参阅不正确的实例化对立模式For more information about why we recommend static clients, see Improper instantiation antipattern.

有关更多 Azure Functions 性能提示,请参阅优化 Azure Functions 的性能和可靠性For more Azure Functions performance tips, see Optimize the performance and reliability of Azure Functions.