Tips voor betere prestaties van Azure Cosmos DB en .NET

VAN TOEPASSING OP: NoSQL

Azure Cosmos DB is een snelle, flexibele gedistribueerde database die naadloos kan worden geschaald met gegarandeerde latentie- en doorvoerniveaus. 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 containerdoorvoer inrichten of databasedoorvoer inrichten voor meer informatie.

Omdat Azure Cosmos DB toegankelijk is via netwerkaanroepen, kunt u optimalisaties aan de clientzijde uitvoeren om piekprestaties te bereiken wanneer u de SQL .NET SDK gebruikt.

Als u de prestaties van uw database wilt verbeteren, kunt u de opties in de volgende secties overwegen.

Aanbevelingen voor hosting

Garbagecollection aan serverzijde inschakelen

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 of tegen tarieven die groter zijn dan 50.000 aanvraageenheden per seconde (RU/s), kan de clienttoepassing een knelpunt voor workloads worden. Dit komt doordat de computer mogelijk een limiet heeft voor CPU- of netwerkgebruik. 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 container 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.

Nieuwste SDK-versies (groter dan 3.23.0) verwijderen deze automatisch wanneer ze deze detecteren, met oudere versies, kunt u deze verwijderen door:

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

Netwerken

Verbinding maken ionbeleid: de modus directe verbinding gebruiken

De standaardverbindingsmodus van .NET V3 SDK is rechtstreeks met tcp-protocol. U configureert de verbindingsmodus wanneer u het CosmosClient exemplaar maakt in CosmosClientOptions. Zie het artikel over connectiviteitsmodi voor meer informatie over verschillende connectiviteitsopties .

string connectionString = "<your-account-connection-string>";
CosmosClient client = new CosmosClient(connectionString,
new CosmosClientOptions
{
    ConnectionMode = ConnectionMode.Gateway // ConnectionMode.Direct is the default
});

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 deze wordt uitgevoerd op het TCP-protocol, optimaliseert de client voor latentie met behulp van de langdurige verbindingen. Dit is in tegenstelling tot het HTTPS-protocol, dat de verbindingen na twee minuten van inactiviteit beëindigt.

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

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 eindigen binnen 1 milliseconden (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.

Plaats clients in dezelfde regio.

Het aantal threads/taken verhogen

Omdat aanroepen naar Azure Cosmos DB via het netwerk worden uitgevoerd, moet u mogelijk de mate van gelijktijdigheid van uw aanvragen variëren, zodat de clienttoepassing zo min mogelijk tijd besteedt aan het wachten tussen aanvragen. 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 om latentie en CPU-jitter te verminderen

Het is raadzaam om de instructies te volgen om versneld netwerken in te schakelen in uw Windows (klik voor instructies) of Linux (klik voor instructies) Azure VM om de prestaties te maximaliseren.

Zonder versneld netwerken kan IO die tussen uw Azure-VM en andere Azure-resources wordt verzonden, onnodig worden gerouteerd via een host en virtuele switch tussen de VM en de bijbehorende netwerkkaart. Als de host en virtuele switch inline in het gegevenspad worden geplaatst, neemt niet alleen de latentie en jitter in het communicatiekanaal toe, maar wordt ook de CPU-cycli van de VIRTUELE machine gestolen. Met versneld netwerken, de VM-interfaces rechtstreeks met de NIC zonder tussenpersonen; alle netwerkbeleidsgegevens die door de host en virtuele switch werden verwerkt, worden nu verwerkt in hardware op de NIC; de host en virtuele switch worden omzeild. Over het algemeen kunt u lagere latentie en hogere doorvoer verwachten, evenals consistentere latentie en een lager CPU-gebruik wanneer u versneld netwerken inschakelt.

Beperkingen: versneld netwerken moeten worden ondersteund op het VM-besturingssysteem en kunnen alleen worden ingeschakeld wanneer de VIRTUELE machine wordt gestopt en de toewijzing ervan ongedaan wordt gemaakt. De VM kan niet worden geïmplementeerd met Azure Resource Manager. App Service heeft geen versneld netwerk ingeschakeld.

Raadpleeg de windows- en Linux-instructies voor meer informatie.

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 om de meest recente SDK te bepalen en verbeteringen te bekijken.

Stream-API's gebruiken

.NET SDK V3 bevat stream-API's die gegevens kunnen ontvangen en retourneren zonder te serialiseren.

Toepassingen in de middelste laag die geen reacties rechtstreeks van de SDK gebruiken, maar deze doorsturen naar andere toepassingslagen, kunnen profiteren van de stream-API's. Zie de voorbeelden van het beheer van items voor voorbeelden van het verwerken van stromen.

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

Elk CosmosClient exemplaar is thread-veilig en voert efficiënt verbindingsbeheer en adrescaching uit wanneer het werkt in de directe modus. 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 voor elk account waarmee uw toepassing communiceert.

Zie de gerelateerde aanbevolen procedures voor multitenant-toepassingen die meerdere accounts verwerken.

Wanneer u aan Azure Functions werkt, moeten instanties ook de bestaande richtlijnen volgen en één exemplaar onderhouden.

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() Container.GetItemLinqQueryable<T>() niet waarvoor blokkerende aanroepen worden gebruikt om de query synchroon leeg te maken. Gebruik ToFeedIterator() 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.

Inhoudsreactie uitschakelen voor schrijfbewerkingen

Voor workloads met zware nettoladingen kunt u de EnableContentResponseOnWrite aanvraagoptie instellen op false. De service retourneert de gemaakte of bijgewerkte resource niet meer naar de SDK. Normaal gesproken heeft de toepassing het object dat wordt gemaakt, niet nodig om het te retourneren. De headerwaarden zijn nog steeds toegankelijk, zoals een aanvraagkosten. Als u het antwoord op inhoud uitschakelt, kunt u de prestaties verbeteren, omdat de SDK geen geheugen meer hoeft toe te wijzen of de hoofdtekst van het antwoord serialiseert. Het vermindert ook het netwerkbandbreedtegebruik om de prestaties verder te helpen.

ItemRequestOptions requestOptions = new ItemRequestOptions() { EnableContentResponseOnWrite = false };
ItemResponse<Book> itemResponse = await this.container.CreateItemAsync<Book>(book, new PartitionKey(book.pk), requestOptions);
// Resource will be null
itemResponse.Resource

Bulk inschakelen om te optimaliseren voor doorvoer in plaats van latentie

Schakel bulksgewijs in voor scenario's waarbij de workload een grote hoeveelheid doorvoer vereist en latentie niet zo belangrijk is. Zie Inleiding tot bulkondersteuning voor meer informatie over het inschakelen van de functie Bulk en voor meer informatie over welke scenario's deze moeten worden gebruikt.

Verhoog System.Net Max Verbinding maken ions per host wanneer u de gatewaymodus gebruikt

Azure Cosmos DB-aanvragen worden uitgevoerd via HTTPS/REST wanneer u de gatewaymodus gebruikt. Ze zijn onderworpen aan de standaardverbindingslimiet per hostnaam of IP-adres. Mogelijk moet u instellen MaxConnections op een hogere waarde (van 100 tot en met 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.Default Verbinding maken ionLimit 50. Als u de waarde wilt wijzigen, kunt u instellen Documents.Client.ConnectionPolicy.MaxConnectionLimit op een hogere waarde.

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 of uitgesloten van indexering met behulp van indexeringspaden (IndexingPolicy.IncludedPaths en IndexingPolicy.ExcludedPaths).

Door alleen de paden te indexeren die u nodig hebt, kunt u schrijfprestaties verbeteren, RU-kosten voor schrijfbewerkingen verminderen en indexopslag verminderen voor scenario's waarin de querypatronen vooraf bekend zijn. Dit komt doordat indexeringskosten rechtstreeks correleren met het aantal unieke paden dat is geïndexeerd. In de volgende code ziet u bijvoorbeeld hoe u een hele sectie van de documenten (een substructuur) kunt uitsluiten van indexering met behulp van het jokerteken *:

var containerProperties = new ContainerProperties(id: "excludedPathCollection", partitionKeyPath: "/pk" );
containerProperties.IndexingPolicy.IncludedPaths.Add(new IncludedPath { Path = "/*" });
containerProperties.IndexingPolicy.ExcludedPaths.Add(new ExcludedPath { Path = "/nonIndexedContent/*");
Container container = await this.cosmosDatabase.CreateContainerAsync(containerProperties);

Zie Het indexeringsbeleid van Azure Cosmos DB voor meer informatie.

Doorvoer

Meten en afstemmen voor lager RU/s-gebruik

Azure Cosmos DB biedt een uitgebreide set databasebewerkingen. Deze bewerkingen omvatten relationele en hiërarchische query's met UDF-bestanden (Universal Disk Format), 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 die nodig zijn om de bewerking te voltooien. In plaats van aan hardwareresources te denken en te beheren, kunt u een aanvraageenheid beschouwen als één meting voor de resources die nodig zijn voor het uitvoeren van verschillende databasebewerkingen en het uitvoeren van een toepassingsaanvraag.

Doorvoer wordt ingericht op basis van het aantal aanvraageenheden dat is ingesteld voor elke container. Verbruik van aanvraageenheden wordt geëvalueerd als een eenheidstarief 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-bestanden 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
ItemResponse<Book> response = await container.CreateItemAsync<Book>(myBook, new PartitionKey(myBook.PkValue));
Console.WriteLine("Insert of item consumed {0} request units", response.RequestCharge);
// Measure the performance (Request Units) of queries
FeedIterator<Book> queryable = container.GetItemQueryIterator<ToDoActivity>(queryString);
while (queryable.HasMoreResults)
    {
        FeedResponse<Book> queryResponse = await queryable.ExecuteNextAsync<Book>();
        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). Als de voorgaande query bijvoorbeeld 1000 1 KB-documenten retourneert, zijn de kosten van de bewerking 1000. Binnen één seconde eert de server slechts twee dergelijke aanvragen voordat deze aanvragen later worden 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). Het retourneert een header x-ms-retry-after-ms die de hoeveelheid tijd aangeeft, in milliseconden, dat de gebruiker moet wachten voordat de aanvraag opnieuw wordt uitgevoerd.

    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 meerdere clients 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 CosmosException met statuscode 429 aan de toepassing.

U kunt het standaardaantal nieuwe pogingen wijzigen door het RetryOptions in te stellen op het CosmosClientOptions exemplaar. De CosmosException met statuscode 429 wordt standaard geretourneerd na een cumulatieve wachttijd van 30 seconden als de aanvraag blijft werken boven de aanvraagsnelheid. Deze fout wordt geretourneerd, 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 wilt voorkomen tijdens prestatieexperimenten, meet u de kosten die door elke bewerking worden geretourneerd en zorgt u ervoor dat aanvragen onder de frequentie van de gereserveerde aanvraag worden uitgevoerd.

Zie Aanvraageenheden voor meer informatie.

Ontwerp voor kleinere documenten voor een hogere doorvoer

De aanvraagkosten (de kosten voor aanvraagverwerking) van een opgegeven bewerking komen rechtstreeks overeen 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.