Hantera anslutningar i Azure Functions
Funktioner i en funktionsapp delar resurser. Bland dessa delade resurser finns anslutningar: HTTP-anslutningar, databasanslutningar och anslutningar till tjänster som Azure Storage. När många funktioner körs samtidigt i en förbrukningsplan går det att få slut på tillgängliga anslutningar. Den här artikeln beskriver hur du kodar dina funktioner för att undvika att använda fler anslutningar än de behöver.
Kommentar
Anslutningsgränser som beskrivs i den här artikeln gäller endast vid körning i en förbrukningsplan. De tekniker som beskrivs här kan dock vara till nytta när du kör någon plan.
Anslutningsgräns
Antalet tillgängliga anslutningar i en förbrukningsplan är begränsat, delvis på grund av att en funktionsapp i den här planen körs i en sandbox-miljö. En av de begränsningar som sandbox-miljön tillämpar på din kod är en gräns för antalet utgående anslutningar, som för närvarande är 600 aktiva (totalt 1 200) anslutningar per instans. När du når den här gränsen skriver funktionskörningen följande meddelande till loggarna: Host thresholds exceeded: Connections
. Mer information finns i Begränsningar för Functions-tjänsten.
Den här gränsen är per instans. När skalningskontrollanten lägger till funktionsappinstanser för att hantera fler begäranden har varje instans en oberoende anslutningsgräns. Det innebär att det inte finns någon global anslutningsgräns och du kan ha mycket mer än 600 aktiva anslutningar i alla aktiva instanser.
När du felsöker kontrollerar du att du har aktiverat Application Insights för funktionsappen. Med Application Insights kan du visa mått för dina funktionsappar som körningar. Mer information finns i Visa telemetri i Application Insights.
Statiska klienter
Undvik att lagra fler anslutningar än nödvändigt genom att återanvända klientinstanser i stället för att skapa nya med varje funktionsanrop. Vi rekommenderar att du återanvänder klientanslutningar för alla språk som du kan skriva funktionen i. Till exempel kan .NET-klienter som HttpClient-, DocumentClient- och Azure Storage-klienter hantera anslutningar om du använder en enda statisk klient.
Här följer några riktlinjer när du använder en tjänstspecifik klient i ett Azure Functions-program:
- Skapa inte en ny klient med varje funktionsanrop.
- Skapa en enda statisk klient som varje funktionsanrop kan använda.
- Överväg att skapa en enda statisk klient i en delad hjälpklass om olika funktioner använder samma tjänst.
Exempel på klientkod
Det här avsnittet visar metodtips för att skapa och använda klienter från din funktionskod.
HTTP-begäranden
Här är ett exempel på C#-funktionskod som skapar en statisk HttpClient-instans :
// 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
}
En vanlig fråga om HttpClient i .NET är "Ska jag ta bort min klient?" I allmänhet tar du bort objekt som implementeras IDisposable
när du är klar med att använda dem. Men du tar inte bort en statisk klient eftersom du inte är klar med att använda den när funktionen slutar. Du vill att den statiska klienten ska vara aktiv under programmets varaktighet.
Azure Cosmos DB-klienter
CosmosClient ansluter till en Azure Cosmos DB-instans. Azure Cosmos DB-dokumentationen rekommenderar att du använder en singleton Azure Cosmos DB-klient under programmets livslängd. I följande exempel visas ett mönster för att göra det i en funktion:
#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
}
Skapa också en fil med namnet "function.proj" för utlösaren och lägg till innehållet nedan:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Azure.Cosmos" Version="3.23.0" />
</ItemGroup>
</Project>
SqlClient-anslutningar
Din funktionskod kan använda .NET Framework Data Provider för SQL Server (SqlClient) för att upprätta anslutningar till en SQL-relationsdatabas. Detta är också den underliggande providern för dataramverk som förlitar sig på ADO.NET, till exempel Entity Framework. Till skillnad från HttpClient - och DocumentClient-anslutningar implementerar ADO.NET anslutningspooler som standard. Men eftersom anslutningarna fortfarande kan ta slut bör du optimera anslutningarna till databasen. Mer information finns i SQL Server-anslutningspooler (ADO.NET).
Dricks
Vissa dataramverk, till exempel Entity Framework, hämtar vanligtvis anslutningssträng från avsnittet ConnectionStrings i en konfigurationsfil. I det här fallet måste du uttryckligen lägga till SQL-databas anslutningssträng i samlingen Anslutningssträngar för dina funktionsappinställningar och i filen local.settings.json i det lokala projektet. Om du skapar en instans av SqlConnection i funktionskoden bör du lagra värdet anslutningssträng i Programinställningar med dina andra anslutningar.
Nästa steg
Mer information om varför vi rekommenderar statiska klienter finns i Felaktig instansieringsantipattern.
Fler prestandatips för Azure Functions finns i Optimera prestanda och tillförlitlighet för Azure Functions.