Tips voor betere prestaties van Azure Cosmos DB Java SDK v4

VAN TOEPASSING OP: NoSQL

Belangrijk

De prestatietips in dit artikel zijn alleen bedoeld voor Azure Cosmos DB Java SDK v4. Bekijk de releaseopmerkingen voor De Java SDK v4 van Azure Cosmos DB, de Maven-opslagplaats en de probleemoplossingsgids voor Azure Cosmos DB Java SDK v4 voor meer informatie. Als u momenteel een oudere versie dan v4 gebruikt, raadpleegt u de gids Migreren naar Azure Cosmos DB Java SDK v4 voor hulp om te upgraden naar v4.

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 of SDK-methode-aanroep. Omdat Azure Cosmos DB echter toegankelijk is via netwerkaanroepen, zijn er optimalisaties aan de clientzijde die u kunt uitvoeren om piekprestaties te bereiken wanneer u Azure Cosmos DB Java SDK v4 gebruikt.

Dus als u 'Hoe kan ik de prestaties van mijn database verbeteren?' vraagt, moet u rekening houden met de volgende opties:

Netwerken

  • Clients in dezelfde Azure-regio plaatsen voor prestaties

Plaats indien mogelijk toepassingen die Azure Cosmos DB aanroepen in dezelfde regio als de Azure Cosmos DB-database. Voor een geschatte vergelijking zijn aanroepen naar Azure Cosmos DB binnen dezelfde regio voltooid binnen 1-2 ms, maar de latentie tussen de west- en oostkust van de VS is >50 ms. Deze latentie kan waarschijnlijk variëren van aanvraag tot aanvraag, afhankelijk van de route die door de aanvraag wordt genomen, omdat deze wordt doorgegeven van de client naar de grens van het Azure-datacenter. De laagst mogelijke latentie wordt bereikt 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.

Afbeelding van het Azure Cosmos DB-verbindingsbeleid

Een app die communiceert met een Azure Cosmos DB-account met meerdere regio's, moet voorkeurslocaties configureren om ervoor te zorgen dat aanvragen naar een regio met meerdere regio's gaan.

Versneld netwerken inschakelen om latentie en CPU-jitter te verminderen

We raden u ten zeerste aan de instructies te volgen om versneld netwerken in te schakelen in uw Windows (selecteer voor instructies) of Linux (selecteer voor instructies) azure-VM om de prestaties te maximaliseren door latentie en CPU-jitter te verminderen.

Zonder versneld netwerken kan IO die tussen uw Azure-VM en andere Azure-resources wordt verzonden, 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 kunnen de VM-interfaces rechtstreeks met de NIC zonder tussenpersonen worden gebruikt. Alle netwerkbeleidsgegevens worden verwerkt in de hardware op de NIC, waarbij de host en virtuele switch worden overgeslagen. 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.

Zie de instructies voor Windows en Linux voor meer informatie.

Configuratie van directe en gatewayverbinding afstemmen

Voor het optimaliseren van configuraties voor directe en gatewaymodusverbindingen, raadpleegt u hoe u verbindingsconfiguraties voor Java SDK v4 kunt afstemmen.

SDK-gebruik

  • De meest recente SDK installeren

De Azure Cosmos DB SDK's worden voortdurend verbeterd om de beste prestaties te bieden. Ga naar de Azure Cosmos DB SDK om de meest recente SDK-verbeteringen te bepalen.

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

Elk Azure Cosmos DB-clientexemplaren is thread-veilig en voert efficiënt verbindingsbeheer en adrescaching uit. Om efficiënt verbindingsbeheer en betere prestaties van de Azure Cosmos DB-client mogelijk te maken, raden we u ten zeerste aan één exemplaar van de Azure Cosmos DB-client te gebruiken voor de levensduur van de toepassing.

  • Het laagste consistentieniveau gebruiken dat is vereist voor uw toepassing

Wanneer u een CosmosClient maakt, is sessie de standaardconsistentie die wordt gebruikt als deze niet expliciet is ingesteld. Als sessieconsistentie niet is vereist door uw toepassingslogica, stelt u de consistentie in op Uiteindelijk. Opmerking: het wordt aanbevolen om ten minste sessieconsistentie te gebruiken in toepassingen die gebruikmaken van de Processor van de wijzigingenfeed van Azure Cosmos DB.

  • Async-API gebruiken om de ingerichte doorvoer te verhogen

Azure Cosmos DB Java SDK v4 bundelt twee API's, een synchrone en een asynchrone. Grofweg implementeert de Async-API SDK-functionaliteit, terwijl de Synchronisatie-API een thin wrapper is die blokkerende aanroepen naar de Async-API maakt. Dit staat in tegenstelling tot de oudere Azure Cosmos DB Async Java SDK v2, die alleen Async-only was, en met de oudere Azure Cosmos DB Sync Java SDK v2, die alleen-synchroniseren was en een afzonderlijke implementatie had.

De keuze van de API wordt bepaald tijdens de initialisatie van de client; een CosmosAsyncClient ondersteunt Async-API, terwijl een CosmosClient ondersteuning biedt voor de Synchronisatie-API.

De Async-API implementeert niet-blokkerende IO en is de optimale keuze als u de doorvoer wilt beperken bij het uitgeven van aanvragen naar Azure Cosmos DB.

Het gebruik van de Synchronisatie-API kan de juiste keuze zijn als u een API wilt of nodig hebt, die de reactie op elke aanvraag blokkeert of als synchrone bewerking het dominante paradigma in uw toepassing is. U kunt bijvoorbeeld de synchronisatie-API gebruiken wanneer u gegevens ophoudt naar Azure Cosmos DB in een microservicestoepassing, mits de doorvoer niet kritiek is.

Let op: synchronisatie-API-doorvoer verslechtert met een toenemende reactietijd van aanvragen, terwijl de Async-API de volledige bandbreedtemogelijkheden van uw hardware kan verzadigen.

Geografische collocatie kan u hogere en consistentere doorvoer bieden bij het gebruik van de Synchronisatie-API (zie Collocate-clients in dezelfde Azure-regio voor prestaties), maar verwacht nog steeds niet dat de Asynchrone API haalbare doorvoer overschrijdt.

Sommige gebruikers zijn mogelijk ook niet bekend met Project Reactor, het Reactieve Streams-framework dat wordt gebruikt om Azure Cosmos DB Java SDK v4 Async API te implementeren. Als dit een probleem is, raden we u aan onze inleidende reactorpatroongids te lezen en vervolgens deze inleiding tot reactief programmeren te bekijken om vertrouwd te raken. Als u Azure Cosmos DB al hebt gebruikt met een Async-interface en de SDK die u hebt gebruikt azure Cosmos DB Async Java SDK v2, bent u mogelijk bekend met ReactiveX/RxJava , maar weet u niet zeker wat er is gewijzigd in Project Reactor. Bekijk in dat geval onze Reactor vs RxJava Guide om vertrouwd te raken.

De volgende codefragmenten laten zien hoe u uw Azure Cosmos DB-client initialiseert voor respectievelijk Async-API- of Synchronisatie-API-bewerking:

Java SDK V4 (Maven com.azure::azure-cosmos) Async API


CosmosAsyncClient client = new CosmosClientBuilder()
        .endpoint(HOSTNAME)
        .key(MASTERKEY)
        .consistencyLevel(CONSISTENCY)
        .buildAsyncClient();

  • Uw clientworkload uitschalen

Als u test op hoge doorvoerniveaus, 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.

Een goede vuistregel is niet groter dan >50% CPU-gebruik op een bepaalde server, om latentie laag te houden.

  • Geschikte Scheduler gebruiken (vermijd het stelen van Io Netty-threads voor gebeurtenislus)

De asynchrone functionaliteit van Azure Cosmos DB Java SDK is gebaseerd op netty non-blocking IO. De SDK gebruikt een vast aantal IO Netty EventLoop-threads (zoveel CPU-kernen waarover de computer beschikt) voor het uitvoeren van IO-bewerkingen. De Flux die door de API wordt geretourneerd, stuurt het resultaat naar een van de gedeelde IO Netty EventLoop-threads. Het is dus belangrijk om de gedeelde IO Netty EventLoop-threads niet te blokkeren. Het uitvoeren van CPU-intensief werk of het blokkeren van bewerkingen op de NETTY-thread van de IO-gebeurtenislus kan een impasse veroorzaken of de SDK-doorvoer aanzienlijk verminderen.

Met de volgende code wordt bijvoorbeeld een cpu-intensief werk uitgevoerd voor de IO netty-thread van de gebeurtenislus:


Mono<CosmosItemResponse<CustomPOJO>> createItemPub = asyncContainer.createItem(item);
createItemPub.subscribe(
        itemResponse -> {
            //this is executed on eventloop IO netty thread.
            //the eventloop thread is shared and is meant to return back quickly.
            //
            // DON'T do this on eventloop IO netty thread.
            veryCpuIntensiveWork();
        });


Nadat het resultaat is ontvangen, moet u voorkomen dat u CPU-intensief werk uitvoert aan het resultaat van de IO-netty-thread van de gebeurtenislus. U kunt in plaats daarvan uw eigen Scheduler opgeven om uw eigen thread te bieden voor het uitvoeren van uw werk, zoals hieronder wordt weergegeven (vereist import reactor.core.scheduler.Schedulers).


Mono<CosmosItemResponse<CustomPOJO>> createItemPub = asyncContainer.createItem(item);
createItemPub
        .publishOn(Schedulers.parallel())
        .subscribe(
                itemResponse -> {
                    //this is now executed on reactor scheduler's parallel thread.
                    //reactor scheduler's parallel thread is meant for CPU intensive work.
                    veryCpuIntensiveWork();
                });

Op basis van het type werk moet u de juiste bestaande Reactor Scheduler voor uw werk gebruiken. Lees hier Schedulers.

Raadpleeg dit blogbericht van Project Reactor voor meer informatie over het threading- en planningsmodel van project Reactor.

Voor meer informatie over Azure Cosmos DB Java SDK v4 raadpleegt u de Azure Cosmos DB-map van de Azure SDK voor Java-monorepo op GitHub.

  • Logboekinstellingen in uw toepassing optimaliseren

Om verschillende redenen moet u logboekregistratie toevoegen aan een thread die een hoge aanvraagdoorvoer genereert. Als u de ingerichte doorvoer van een container volledig wilt verzadigen met aanvragen die door deze thread worden gegenereerd, kunnen optimalisaties voor logboekregistratie de prestaties aanzienlijk verbeteren.

  • Een asynchrone logboekregistratie configureren

De latentie van een synchrone logboekregistratie factoren noodzakelijkerwijs in de totale latentieberekening van uw aanvraag genererende thread. Een asynchrone logboekregistratie, zoals log4j2 , wordt aanbevolen om de overhead van logboekregistratie los te koppelen van uw toepassingsthreads met hoge prestaties.

  • Logboekregistratie van Netty uitschakelen

Logboekregistratie van Netty-bibliotheken is chatty en moet worden uitgeschakeld (het onderdrukken van de aanmeldingsconfiguratie is mogelijk niet voldoende) om extra CPU-kosten te voorkomen. Als u zich niet in de foutopsporingsmodus bevindt, schakelt u de logboekregistratie van Netty helemaal uit. Dus als u Log4j gebruikt om de extra CPU-kosten te verwijderen die door org.apache.log4j.Category.callAppenders() Netty worden gemaakt, voegt u de volgende regel toe aan uw codebasis:

org.apache.log4j.Logger.getLogger("io.netty").setLevel(org.apache.log4j.Level.OFF);
  • Resourcelimiet voor openen van besturingssysteembestanden

Sommige Linux-systemen (zoals Red Hat) hebben een bovengrens voor het aantal geopende bestanden en dus het totale aantal verbindingen. Voer het volgende uit om de huidige limieten weer te geven:

ulimit -a

Het aantal geopende bestanden (nofile) moet groot genoeg zijn om voldoende ruimte te hebben voor de geconfigureerde grootte van de verbindingsgroep en andere geopende bestanden door het besturingssysteem. Het kan worden gewijzigd om een grotere verbindingsgroepgrootte toe te staan.

Open het bestand limits.conf:

vim /etc/security/limits.conf

Voeg de volgende regels toe/wijzigt:

* - nofile 100000
  • Partitiesleutel opgeven in puntschrijfbewerkingen

Als u de prestaties van puntschrijfbewerkingen wilt verbeteren, geeft u de partitiesleutel voor items op in de API-aanroep voor puntschrijfbewerkingen, zoals hieronder wordt weergegeven:

Java SDK V4 (Maven com.azure::azure-cosmos) Async API

asyncContainer.createItem(item,new PartitionKey(pk),new CosmosItemRequestOptions()).block();

In plaats van alleen het itemexemplaren op te geven, zoals hieronder wordt weergegeven:

Java SDK V4 (Maven com.azure::azure-cosmos) Async API

asyncContainer.createItem(item).block();

De laatste wordt ondersteund, maar voegt latentie toe aan uw toepassing; de SDK moet het item parseren en de partitiesleutel extraheren.

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 opgeven welke documentpaden moeten worden opgenomen of uitgesloten van indexering met behulp van indexeringspaden (setIncludedPaths en setExcludedPaths). Het gebruik van indexeringspaden kan betere schrijfprestaties en lagere indexopslag bieden voor scenario's waarin de querypatronen vooraf bekend zijn, omdat indexeringskosten rechtstreeks worden gecorreleerd aan het aantal unieke paden dat is geïndexeerd. In de volgende code ziet u bijvoorbeeld hoe u volledige secties van de documenten (ook wel substructuur genoemd) kunt opnemen en uitsluiten van indexering met behulp van het jokerteken *.


CosmosContainerProperties containerProperties = new CosmosContainerProperties(containerName, "/lastName");

// Custom indexing policy
IndexingPolicy indexingPolicy = new IndexingPolicy();
indexingPolicy.setIndexingMode(IndexingMode.CONSISTENT);

// Included paths
List<IncludedPath> includedPaths = new ArrayList<>();
includedPaths.add(new IncludedPath("/*"));
indexingPolicy.setIncludedPaths(includedPaths);

// Excluded paths
List<ExcludedPath> excludedPaths = new ArrayList<>();
excludedPaths.add(new ExcludedPath("/name/*"));
indexingPolicy.setExcludedPaths(excludedPaths);

containerProperties.setIndexingPolicy(indexingPolicy);

ThroughputProperties throughputProperties = ThroughputProperties.createManualThroughput(400);

database.createContainerIfNotExists(containerProperties, throughputProperties);
CosmosAsyncContainer containerIfNotExists = database.getContainer(containerName);

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, waaronder relationele en hiërarchische query's met UDF's, opgeslagen procedures en triggers, die allemaal werken op de documenten in een databaseverzameling. De kosten die gepaard gaan met elke bewerking hangen af van de CPU, de IO en het geheugen, vereist om de bewerking uit te voeren. In plaats van aan hardwareresources te denken en te beheren, kunt u een aanvraageenheid (RU) 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 tarief per seconde. Toepassingen die de ingerichte aanvraageenheidsnelheid voor hun container overschrijden, zijn 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 heeft invloed op het aantal aanvraageenheden dat wordt verbruikt voor een bewerking. 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 om het aantal aanvraageenheden te meten dat door deze bewerkingen wordt verbruikt. U kunt ook de equivalente eigenschap RequestCharge bekijken in ResourceResponse<T> of FeedResponse<T>.

Java SDK V4 (Maven com.azure::azure-cosmos) Async API

CosmosItemResponse<CustomPOJO> response = asyncContainer.createItem(item).block();

response.getRequestCharge();

De aanvraagkosten die in deze header worden geretourneerd, zijn een fractie van uw ingerichte doorvoer. Als u bijvoorbeeld 2000 RU/s hebt ingericht en als de voorgaande query 1000 kB-documenten retourneert, zijn de kosten van de bewerking 1000. Daarom eert de server binnen één seconde slechts twee dergelijke aanvragen voordat de frequentie van volgende 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) en retourneert de header x-ms-retry-after-ms die de hoeveelheid tijd aangeeft, in milliseconden, dat de gebruiker moet wachten voordat de aanvraag opnieuw wordt geïmplementeerd.

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 CosmosClientException met statuscode 429 aan de toepassing. Het standaardaantal nieuwe pogingen kan worden gewijzigd met behulp van setMaxRetryAttemptsOnThrottledRequests() het ThrottlingRetryOptions exemplaar. De CosmosClientException met statuscode 429 wordt standaard geretourneerd na een cumulatieve wachttijd van 30 seconden als de aanvraag blijft werken boven de aanvraagsnelheid. Dit gebeurt zelfs wanneer het huidige aantal nieuwe pogingen kleiner is dan het maximumaantal nieuwe pogingen, of het nu de standaardwaarde is van 9 of een door de gebruiker gedefinieerde waarde.

Hoewel het geautomatiseerde gedrag voor opnieuw proberen helpt om de tolerantie en bruikbaarheid voor de meeste toepassingen te verbeteren, kan het even vreemd komen bij het uitvoeren van prestatiebenchmarks, met name bij het meten van latentie. 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.

  • Ontwerpen voor kleinere documenten voor hogere doorvoer

De aanvraagkosten (de aanvraagverwerkingskosten) van een bepaalde bewerking worden rechtstreeks gecorreleerd aan de grootte van het document. Bewerkingen op grote documenten kosten meer dan bewerkingen voor kleine documenten. U kunt uw toepassing en werkstromen het beste ontwerpen om de grootte van uw item ongeveer 1 kB of vergelijkbare volgorde of grootte te geven. Voor latentiegevoelige toepassingen moeten grote items worden vermeden: documenten met meerdere MB vertragen uw toepassing.

Volgende stappen

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

Wilt u capaciteitsplanning uitvoeren voor een migratie naar Azure Cosmos DB? U kunt informatie over uw bestaande databasecluster gebruiken voor capaciteitsplanning.