Share via


Tips voor betere prestaties van Azure Cosmos DB en .NET SDK v2

VAN TOEPASSING OP: NoSQL

Azure Cosmos DB is een snelle en flexibele gedistribueerde database die naadloos wordt geschaald met gegarandeerde latentie en doorvoer. U hoeft geen belangrijke architectuurwijzigingen aan te brengen of complexe code te schrijven om uw database te schalen met Azure Cosmos DB. Omhoog en omlaag schalen is net zo eenvoudig als het maken van één API-aanroep. Zie voor meer informatie hoe u containerdoorvoer inricht of hoe u databasedoorvoer inricht. Maar omdat Azure Cosmos DB toegankelijk is via netwerkaanroepen, zijn er optimalisaties aan de clientzijde die u kunt uitvoeren om piekprestaties te bereiken wanneer u de SQL .NET SDK gebruikt.

Als u de databaseprestaties probeert te verbeteren, kunt u de volgende opties overwegen:

Upgrade uitvoeren naar de .NET V3 SDK

De .NET v3 SDK wordt uitgebracht. Als u de .NET v3 SDK gebruikt, raadpleegt u de prestatiehandleiding voor .NET v3 voor de volgende informatie:

  • Standaard ingesteld op directe TCP-modus
  • Stream-API-ondersteuning
  • Ondersteuning voor aangepaste serializer om System.Text.JSON gebruik toe te staan
  • Geïntegreerde batch- en bulkondersteuning

Aanbevelingen voor hosting

Garbagecollection aan serverzijde inschakelen (GC)

Het verminderen van de frequentie van garbagecollection kan in sommige gevallen helpen. Stel in .NET gcServer in op true.

Uw clientworkload uitschalen

Als u test op hoge doorvoerniveaus (meer dan 50.000 RU/s), kan de clienttoepassing het knelpunt worden omdat de computer het CPU- of netwerkgebruik beperkt. Als u dit punt bereikt, kunt u het Azure Cosmos DB-account verder pushen door uw clienttoepassingen uit te schalen op meerdere servers.

Notitie

Hoog CPU-gebruik kan leiden tot verhoogde latentie en time-outuitzondering van aanvragen.

Metagegevensbewerkingen

Controleer niet of een database en/of verzameling bestaat door aan te roepen Create...IfNotExistsAsync en/of Read...Async in het dynamische pad en/of voordat u een itembewerking uitvoert. De validatie moet alleen worden uitgevoerd bij het opstarten van de toepassing wanneer dit nodig is, als u verwacht dat ze worden verwijderd (anders is deze niet nodig). Deze metagegevensbewerkingen genereren extra end-to-endlatentie, hebben geen SLA en hun eigen afzonderlijke beperkingen die niet worden geschaald, zoals gegevensbewerkingen.

Logboekregistratie en tracering

Voor sommige omgevingen is . NET DefaultTraceListener ingeschakeld. De DefaultTraceListener veroorzaakt prestatieproblemen in productieomgevingen die een hoog CPU- en I/O-knelpunt veroorzaken. Controleer en zorg ervoor dat defaultTraceListener is uitgeschakeld voor uw toepassing door deze uit de TraceListeners in productieomgevingen te verwijderen.

De nieuwste SDK-versies (groter dan 2.16.2) worden automatisch verwijderd wanneer ze deze detecteren, met oudere versies, kunt u deze verwijderen door:

if (!Debugger.IsAttached)
{
    Type defaultTrace = Type.GetType("Microsoft.Azure.Documents.DefaultTrace,Microsoft.Azure.DocumentDB.Core");
    TraceSource traceSource = (TraceSource)defaultTrace.GetProperty("TraceSource").GetValue(null);
    traceSource.Listeners.Remove("Default");
    // Add your own trace listeners
}

Netwerken

Verbindingsbeleid: de modus Directe verbinding gebruiken

De standaardverbindingsmodus voor .NET V2 SDK is een gateway. U configureert de verbindingsmodus tijdens de bouw van het DocumentClient exemplaar met behulp van de ConnectionPolicy parameter. Als u de directe modus gebruikt, moet u ook de Protocol ConnectionPolicy parameter instellen. Zie het artikel over connectiviteitsmodi voor meer informatie over verschillende connectiviteitsopties .

Uri serviceEndpoint = new Uri("https://contoso.documents.net");
string authKey = "your authKey from the Azure portal";
DocumentClient client = new DocumentClient(serviceEndpoint, authKey,
new ConnectionPolicy
{
   ConnectionMode = ConnectionMode.Direct, // ConnectionMode.Gateway is the default
   ConnectionProtocol = Protocol.Tcp
});

Tijdelijke poortuitputting

Als u een hoog verbindingsvolume of hoog poortgebruik op uw exemplaren ziet, controleert u eerst of uw clientexemplaren singletons zijn. Met andere woorden, de clientexemplaren moeten uniek zijn voor de levensduur van de toepassing.

Wanneer de client wordt uitgevoerd op het TCP-protocol, optimaliseert de client voor latentie met behulp van de langdurige verbindingen in plaats van het HTTPS-protocol, waardoor de verbindingen na 2 minuten inactiviteit worden beëindigd.

In scenario's waarin u sparse-toegang hebt en als u een hoger aantal verbindingen ziet in vergelijking met de toegang tot de gatewaymodus, kunt u het volgende doen:

  • Configureer de eigenschap ConnectionPolicy.PortReuseMode op PrivatePortPool (effectief met framework version>= 4.6.1 en .NET core version >= 2.0): Met deze eigenschap kan de SDK een kleine groep tijdelijke poorten gebruiken voor verschillende Azure Cosmos DB-doeleindpunten.
  • Configureer de eigenschap ConnectionPolicy.IdleConnectionTimeout moet groter zijn dan of gelijk zijn aan 10 minuten. De aanbevolen waarden liggen tussen 20 minuten en 24 uur.

OpenAsync aanroepen om opstartlatentie bij eerste aanvraag te voorkomen

De eerste aanvraag heeft standaard een hogere latentie omdat deze de adresrouteringstabel moet ophalen. Wanneer u SDK V2 gebruikt, roept OpenAsync() u één keer aan tijdens de initialisatie om deze opstartlatentie op de eerste aanvraag te voorkomen. De aanroep ziet er als volgt uit: await client.OpenAsync();

Notitie

OpenAsync genereert aanvragen voor het verkrijgen van de adresrouteringstabel voor alle containers in het account. Voor accounts met veel containers, maar waarvan de toepassing toegang heeft tot een subset ervan, OpenAsync zou een onnodige hoeveelheid verkeer genereren, waardoor de initialisatie traag zou worden. Het gebruik is OpenAsync dus mogelijk niet nuttig in dit scenario omdat het opstarten van de toepassing wordt vertraagd.

Voor prestaties plaatst u clients in dezelfde Azure-regio

Plaats indien mogelijk toepassingen die Azure Cosmos DB aanroepen in dezelfde regio als de Azure Cosmos DB-database. Hier volgt een geschatte vergelijking: aanroepen naar Azure Cosmos DB binnen dezelfde regio zijn voltooid binnen 1 ms tot 2 ms, maar de latentie tussen de west- en oostkust van de VS is meer dan 50 ms. Deze latentie kan variëren van aanvraag tot aanvraag, afhankelijk van de route die door de aanvraag wordt genomen wanneer deze wordt doorgegeven van de client naar de grens van het Azure-datacenter. U kunt de laagst mogelijke latentie krijgen door ervoor te zorgen dat de aanroepende toepassing zich in dezelfde Azure-regio bevindt als het ingerichte Azure Cosmos DB-eindpunt. Zie Azure-regio's voor een lijst met beschikbare regio's.

Het Azure Cosmos DB-verbindingsbeleid

Het aantal threads/taken verhogen

Omdat aanroepen naar Azure Cosmos DB via het netwerk worden uitgevoerd, moet u mogelijk de mate van parallelle uitvoering van uw aanvragen variëren, zodat de clienttoepassing zo min mogelijk tijd tussen aanvragen hoeft te wachten. Als u bijvoorbeeld de .NET Task Parallel Library gebruikt, maakt u de volgorde van honderden taken die lezen van of schrijven naar Azure Cosmos DB.

Versneld netwerken inschakelen

Als u latentie en CPU-jitter wilt verminderen, raden we u aan versneld netwerken in te schakelen op virtuele clientmachines. Zie Een virtuele Windows-machine maken met versneld netwerken of een virtuele Linux-machine maken met versneld netwerken.

SDK-gebruik

De meest recente SDK installeren

De Azure Cosmos DB SDK's worden voortdurend verbeterd om de beste prestaties te bieden. Zie de Azure Cosmos DB SDK-pagina's om de meest recente SDK te bepalen en verbeteringen te bekijken.

Een Singleton Azure Cosmos DB-client gebruiken voor de levensduur van uw toepassing

Elk DocumentClient exemplaar is thread-veilig en voert efficiënt verbindingsbeheer en adrescaching uit wanneer u in de directe modus werkt. Om efficiënt verbindingsbeheer en betere SDK-clientprestaties mogelijk te maken, raden we u aan één exemplaar per AppDomain levensduur van de toepassing te gebruiken.

Voorkomen dat oproepen worden geblokkeerd

Azure Cosmos DB SDK moet zijn ontworpen om veel aanvragen tegelijkertijd te verwerken. Met asynchrone API's kan een kleine groep threads duizenden gelijktijdige aanvragen verwerken door niet te wachten op blokkeringsaanroepen. In plaats van te wachten op een langlopende synchrone taak om te voltooien, kan de thread aan een andere aanvraag werken.

Een veelvoorkomend prestatieprobleem in apps die gebruikmaken van de Azure Cosmos DB SDK blokkeert aanroepen die asynchroon kunnen zijn. Veel synchrone blokkeringsaanroepen leiden tot starvatie van threadgroepen en verminderde reactietijden.

Niet:

  • Blokkeer asynchrone uitvoering door Task.Wait of Task.Result aan te roepen.
  • Gebruik Task.Run om een synchrone API asynchroon te maken.
  • Verwerf vergrendelingen in algemene codepaden. Azure Cosmos DB .NET SDK is het meest presterend wanneer deze is ontworpen om code parallel uit te voeren.
  • Roep Task.Run aan en wacht er onmiddellijk op. ASP.NET Core al app-code uitvoert op normale Thread Pool-threads, waardoor het aanroepen van Task.Run alleen resulteert in extra onnodige threadpoolplanning. Zelfs als de geplande code een thread blokkeert, voorkomt Task.Run dat niet.
  • Gebruik ToList() DocumentClient.CreateDocumentQuery(...) waarvoor blokkeringsaanroepen worden gebruikt om de query synchroon leeg te maken. Gebruik AsDocumentQuery() om de query asynchroon leeg te maken.

Doe het volgende:

  • Roep de Azure Cosmos DB .NET API's asynchroon aan.
  • De volledige aanroepstack is asynchroon om te profiteren van asynchrone/wachtende patronen.

Een profiler, zoals PerfView, kan worden gebruikt om threads te vinden die vaak worden toegevoegd aan de threadgroep. De Microsoft-Windows-DotNETRuntime/ThreadPoolWorkerThread/Start gebeurtenis geeft een thread aan die is toegevoegd aan de threadgroep.

Verhoog System.Net MaxConnections per host wanneer u de gatewaymodus gebruikt

Azure Cosmos DB-aanvragen worden gedaan via HTTPS/REST wanneer u de gatewaymodus gebruikt. Ze worden onderworpen aan de standaardverbindingslimiet per hostnaam of IP-adres. Mogelijk moet u instellen MaxConnections op een hogere waarde (100 tot 1000), zodat de clientbibliotheek meerdere gelijktijdige verbindingen met Azure Cosmos DB kan gebruiken. In .NET SDK 1.8.0 en hoger is de standaardwaarde voor ServicePointManager.DefaultConnectionLimit 50. Als u de waarde wilt wijzigen, kunt u Documents.Client.ConnectionPolicy.MaxConnectionLimit instellen op een hogere waarde.

Uitstel implementeren met intervallen van RetryAfter

Tijdens het testen van de prestaties moet u de belasting verhogen totdat een klein aantal aanvragen wordt beperkt. Als aanvragen worden beperkt, moet de clienttoepassing weer worden uitgeschakeld voor de vertraging voor het door de server opgegeven interval voor opnieuw proberen. Het respecteren van de uitstel zorgt ervoor dat u een minimale hoeveelheid tijd besteedt aan het wachten tussen nieuwe pogingen.

Ondersteuning voor beleid voor opnieuw proberen is opgenomen in deze SDK's:

Zie RetryAfter voor meer informatie.

In versie 1.19 en hoger van de .NET SDK is er een mechanisme voor het vastleggen van aanvullende diagnostische gegevens en het oplossen van latentieproblemen, zoals wordt weergegeven in het volgende voorbeeld. U kunt de diagnostische tekenreeks registreren voor aanvragen met een hogere leeslatentie. De vastgelegde diagnostische tekenreeks helpt u te begrijpen hoe vaak u 429-fouten voor een bepaalde aanvraag hebt ontvangen.

ResourceResponse<Document> readDocument = await this.readClient.ReadDocumentAsync(oldDocuments[i].SelfLink);
readDocument.RequestDiagnosticsString 

Document-URI's in cache opslaan voor een lagere leeslatentie

Cache document-URI's waar mogelijk voor de beste leesprestaties. U moet logica definiëren om de resource-id in de cache op te cachen wanneer u een resource maakt. Zoekacties op basis van resource-id's zijn sneller dan op naam gebaseerde zoekacties, dus als u deze waarden in de cache opneemt, worden de prestaties verbeterd.

Het aantal threads/taken verhogen

Zie Het aantal threads/taken verhogen in de sectie netwerken van dit artikel.

Querybewerkingen

Zie de prestatietips voor querybewerkingen voor query's.

Indexeringsbeleid

Niet-gebruikte paden uitsluiten van indexering voor snellere schrijfbewerkingen

Met het indexeringsbeleid van Azure Cosmos DB kunt u ook opgeven welke documentpaden moeten worden opgenomen in of uitgesloten van indexering met behulp van indexeringspaden (IndexingPolicy.IncludedPaths en IndexingPolicy.ExcludedPaths). Indexeringspaden kunnen de schrijfprestaties verbeteren en de indexopslag verminderen voor scenario's waarin de querypatronen van tevoren bekend zijn. Dit komt doordat indexeringskosten rechtstreeks correleren met het aantal unieke paden dat is geïndexeerd. Deze code laat bijvoorbeeld zien hoe u een hele sectie van de documenten (een substructuur) kunt uitsluiten van indexering met behulp van het jokerteken *:

var collection = new DocumentCollection { Id = "excludedPathCollection" };
collection.IndexingPolicy.IncludedPaths.Add(new IncludedPath { Path = "/*" });
collection.IndexingPolicy.ExcludedPaths.Add(new ExcludedPath { Path = "/nonIndexedContent/*");
collection = await client.CreateDocumentCollectionAsync(UriFactory.CreateDatabaseUri("db"), collection);

Zie Het indexeringsbeleid van Azure Cosmos DB voor meer informatie.

Doorvoer

Meten en afstemmen op lagere aanvraageenheden/tweede gebruik

Azure Cosmos DB biedt een uitgebreide set databasebewerkingen. Deze bewerkingen omvatten relationele en hiërarchische query's met UDF's, opgeslagen procedures en triggers, die allemaal worden uitgevoerd op de documenten in een databaseverzameling. De kosten die aan elk van deze bewerkingen zijn gekoppeld, variëren afhankelijk van de CPU, IO en het geheugen dat nodig is om de bewerking te voltooien. In plaats van nadenken over en het beheren van hardware, kunt u een aanvraageenheid (RU) bedenken als meting voor de vereiste middelen om verschillende databasebewerkingen uit te voeren, en vervolgens een toepassingsaanvraag indienen.

Doorvoer wordt ingericht op basis van het aantal aanvraageenheden dat is ingesteld voor elke container. Verbruik van aanvraageenheden wordt geëvalueerd als een tarief per seconde. Toepassingen die de ingerichte aanvraageenheidsnelheid voor hun container overschrijden, worden beperkt totdat de snelheid lager is dan het ingerichte niveau voor de container. Als uw toepassing een hoger doorvoerniveau vereist, kunt u de doorvoer verhogen door extra aanvraageenheden in te richten.

De complexiteit van een query is van invloed op het aantal aanvraageenheden dat voor een bewerking wordt verbruikt. Het aantal predicaten, de aard van de predicaten, het aantal UDF's en de grootte van de brongegevensset zijn allemaal van invloed op de kosten van querybewerkingen.

Als u de overhead van een bewerking wilt meten (maken, bijwerken of verwijderen), inspecteert u de header x-ms-request-charge (of de equivalente RequestCharge eigenschap in ResourceResponse\<T> of FeedResponse\<T> in de .NET SDK) om het aantal aanvraageenheden te meten dat door de bewerkingen wordt gebruikt:

// Measure the performance (Request Units) of writes
ResourceResponse<Document> response = await client.CreateDocumentAsync(collectionSelfLink, myDocument);
Console.WriteLine("Insert of document consumed {0} request units", response.RequestCharge);
// Measure the performance (Request Units) of queries
IDocumentQuery<dynamic> queryable = client.CreateDocumentQuery(collectionSelfLink, queryString).AsDocumentQuery();
while (queryable.HasMoreResults)
    {
        FeedResponse<dynamic> queryResponse = await queryable.ExecuteNextAsync<dynamic>();
        Console.WriteLine("Query batch consumed {0} request units", queryResponse.RequestCharge);
    }

De aanvraagkosten die in deze header worden geretourneerd, zijn een fractie van uw ingerichte doorvoer (dat wil gezegd 2000 RU's per seconde). Als de voorgaande query bijvoorbeeld 1000 1 KB-documenten retourneert, zijn de kosten van de bewerking 1000. Binnen één seconde eert de server dus slechts twee dergelijke aanvragen voordat de frequentielimiet voor latere aanvragen wordt beperkt. Zie Aanvraageenheden en de rekenmachine voor aanvraageenheden voor meer informatie.

Snelheidsbeperking/aanvraagsnelheid te groot verwerken

Wanneer een client de gereserveerde doorvoer voor een account probeert te overschrijden, is er geen prestatievermindering op de server en is er geen gebruik van doorvoercapaciteit buiten het gereserveerde niveau. De server beëindigt de aanvraag met RequestRateTooLarge (HTTP-statuscode 429). Er wordt een x-ms-retry-after-ms-header geretourneerd die de hoeveelheid tijd aangeeft, in milliseconden, dat de gebruiker moet wachten voordat de aanvraag opnieuw wordt geprobeerd.

HTTP Status 429,
Status Line: RequestRateTooLarge
x-ms-retry-after-ms :100

De SDK's vangen dit antwoord impliciet op, respecteren de server opgegeven nieuwe poging na header en probeer de aanvraag opnieuw. Tenzij uw account gelijktijdig wordt geopend door meerdere clients, slaagt de volgende nieuwe poging.

Als u meer dan één client cumulatief boven de aanvraagsnelheid hebt, is het standaardaantal nieuwe pogingen dat momenteel is ingesteld op 9 intern door de client mogelijk niet voldoende. In dit geval genereert de client een DocumentClientException met statuscode 429 aan de toepassing.

U kunt het standaardaantal nieuwe pogingen wijzigen door het RetryOptions in te stellen op het ConnectionPolicy exemplaar. De DocumentClientException met statuscode 429 wordt standaard geretourneerd na een cumulatieve wachttijd van 30 seconden als de aanvraag blijft werken boven de aanvraagsnelheid. Deze fout retourneert zelfs wanneer het huidige aantal nieuwe pogingen kleiner is dan het maximumaantal nieuwe pogingen, of de huidige waarde de standaardwaarde is van 9 of een door de gebruiker gedefinieerde waarde.

Het geautomatiseerde gedrag voor opnieuw proberen helpt de tolerantie en bruikbaarheid voor de meeste toepassingen te verbeteren. Maar het is misschien niet het beste gedrag wanneer u prestatiebenchmarks uitvoert, met name wanneer u latentie meet. De door de client waargenomen latentie zal pieken als het experiment de server beperkt en ervoor zorgt dat de client-SDK op de achtergrond opnieuw probeert. Als u latentiepieken tijdens prestatieexperimenten wilt voorkomen, meet u de kosten die door elke bewerking worden geretourneerd en zorgt u ervoor dat aanvragen onder de gereserveerde aanvraagsnelheid worden uitgevoerd. Zie Aanvraageenheden voor meer informatie.

Ontwerp voor kleinere documenten voor een hogere doorvoer

De aanvraagkosten (dat wil gezegd de kosten voor aanvraagverwerking) van een bepaalde bewerking correleren rechtstreeks met de grootte van het document. Bewerkingen op grote documenten kosten meer dan bewerkingen op kleine documenten.

Volgende stappen

Voor een voorbeeldtoepassing die wordt gebruikt om Azure Cosmos DB te evalueren voor scenario's met hoge prestaties op een paar clientcomputers, raadpleegt u Prestatie- en schaaltests met Azure Cosmos DB.

Zie Partitioneren en schalen in Azure Cosmos DB voor meer informatie over het ontwerpen van uw toepassing voor schaalaanpassing en hoge prestaties.