Skip to content

Managing Connections

Tom Dykstra edited this page Jun 7, 2018 · 3 revisions

NOTE: This wiki page has been replaced by an article published on docs.microsoft.com. The wiki page is no longer being maintained and will eventually be deleted.

Functions within a function application share resources. This means that multiple functions can be running at the same time. When using the consumption plan, the scale controller will use heuristics to determine whether to add additional instances to your function application. However, each instance of the application will likely be invoking your functions many times at once.

In the consumption plan, a function app runs inside of the Azure Web App Sandbox, which imposes some specific restrictions on what your code is allowed to do. One of the most notable restrictions is the cap on "Connections", which is currently limited to 300. With a recent release of Functions, you'll see a log message indicating Host thresholds exceeded: Connections when you approach this limit.

In many cases, this connection limit can be avoided by re-using client instances rather than creating new ones in each function. .NET clients like the HttpClient, DocumentClient, and Azure storage clients can manage connections if you use a single, static client. If those clients are re-instantiated with every function invocation, there is a high probability that the code is leaking connections.

As a general rule, when using a service-specific client in a Function application:

  • DO NOT create a new client with every function invocation.
  • DO create a single, static client that can be used by every function invocation.
  • CONSIDER creating a single, static client in a shared helper class if different functions will be using the same service.

HttpClient

A common question about the .NET HttpClient is: "Should I be disposing my client?". In general, you should be disposing objects that implement IDisposable when you are done using them. In the case of a Function application, you want this client to live for the duration of your application, not for the duration of a single request or function invocation.

A lot of documentation about reusing service broker classes focus on HttpClient, but the pattern applies elsewhere as well. For examples, see:

Most articles talk about Web applications, but the pattern applies to Function applications as well. In the case of a function, it's better to create a static HttpClient:

// Create a single, static HttpClient
private static HttpClient httpClient = new HttpClient();

public static async Task Run(string input)
{
    var response = await httpClient.GetAsync("http://example.com");
    // Rest of function
}

DocumentClient

DocumentClient is very similar to HttpClient in its behavior. Creating a single, static instance will yield greater performance, expecially in a high-throughput function.

The DocumentClient perfomance tips includes the recommendation to:

Use a singleton Azure Cosmos DB client for the lifetime of your application.

See also: Azure Cosmos DB + Functions Cookbook— static client

This DocumentClient example shows one pattern you can use for initializing your static client 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
}
Clone this wiki locally
You can’t perform that action at this time.