Prestandatips för Azure Cosmos DB Java SDK v4
GÄLLER FÖR: NoSQL
Viktigt!
Prestandatipsen i den här artikeln gäller endast för Azure Cosmos DB Java SDK v4. Mer information finns i felsökningsguiden för Java SDK v4 i Azure Cosmos DB Java SDK v4, Maven-lagringsplatsen och Azure Cosmos DB Java SDK v4. Om du för närvarande använder en äldre version än v4 kan du läsa guiden Migrera till Azure Cosmos DB Java SDK v4 för hjälp med att uppgradera till v4.
Azure Cosmos DB är en snabb och flexibel distribuerad databas som skalas sömlöst med garanterad svarstid och dataflöde. Du behöver inte göra större arkitekturändringar eller skriva komplex kod för att skala databasen med Azure Cosmos DB. Det är lika enkelt att skala upp och ned som att göra ett enda API-anrop eller ett SDK-metodanrop. Men eftersom Azure Cosmos DB nås via nätverksanrop finns det optimeringar på klientsidan som du kan göra för att uppnå högsta prestanda när du använder Azure Cosmos DB Java SDK v4.
Så om du frågar "Hur kan jag förbättra mina databasprestanda?" bör du överväga följande alternativ:
Nätverk
Samla klienter i samma Azure-region för prestanda
När det är möjligt placerar du alla program som anropar Azure Cosmos DB i samma region som Azure Cosmos DB-databasen. För en ungefärlig jämförelse slutförs anrop till Azure Cosmos DB inom samma region inom 1–2 ms, men svarstiden mellan USA:s västra och östra kust är >50 ms. Den här svarstiden kan sannolikt variera från begäran till begäran beroende på vilken väg begäran tar när den skickas från klienten till Gränsen för Azure-datacenter. Den lägsta möjliga svarstiden uppnås genom att säkerställa att det anropande programmet finns i samma Azure-region som den etablerade Azure Cosmos DB-slutpunkten. En lista över tillgängliga regioner finns i Azure-regioner.
En app som interagerar med ett Azure Cosmos DB-konto i flera regioner måste konfigurera önskade platser för att säkerställa att begäranden går till en samordnad region.
Aktivera accelererat nätverk för att minska svarstiden och CPU-jitter
Vi rekommenderar starkt att du följer anvisningarna för att aktivera accelererat nätverk i windows (välj instruktioner) eller Linux (välj instruktioner) virtuella Azure-datorer för att maximera prestanda genom att minska svarstiden och CPU-jitter.
Utan accelererat nätverk kan I/O som överförs mellan din virtuella Azure-dator och andra Azure-resurser dirigeras via en värd och en virtuell växel mellan den virtuella datorn och dess nätverkskort. Att ha värden och den virtuella växeln infogade i datasökvägen ökar inte bara svarstiden och jitter i kommunikationskanalen, utan stjäl även CPU-cykler från den virtuella datorn. Med accelererat nätverk gränssnittar den virtuella datorn direkt med nätverkskortet utan mellanhänder. All information om nätverksprinciper hanteras i maskinvaran på nätverkskortet och kringgår värden och den virtuella växeln. Vanligtvis kan du förvänta dig lägre svarstid och högre dataflöde, samt mer konsekvent svarstid och minskad CPU-användning när du aktiverar accelererat nätverk.
Begränsningar: Accelererat nätverk måste stödjas på det virtuella datoroperativsystemet och kan bara aktiveras när den virtuella datorn stoppas och frigörs. Det går inte att distribuera den virtuella datorn med Azure Resource Manager. App Service har inget accelererat nätverk aktiverat.
Mer information finns i Windows- och Linux-instruktionerna.
Hög tillgänglighet
Allmän vägledning om hur du konfigurerar hög tillgänglighet i Azure Cosmos DB finns i Hög tillgänglighet i Azure Cosmos DB.
Förutom en bra grundläggande konfiguration i databasplattformen finns det specifika tekniker som kan implementeras i själva Java SDK, vilket kan hjälpa dig i avbrottsscenarier. Två viktiga strategier är den tröskelvärdesbaserade tillgänglighetsstrategin och kretsbrytaren på partitionsnivå.
De här teknikerna tillhandahåller avancerade mekanismer för att hantera specifika svarstids- och tillgänglighetsutmaningar, utöver de återförsöksfunktioner mellan regioner som är inbyggda i SDK:et som standard. Genom att proaktivt hantera potentiella problem på begäran- och partitionsnivå kan dessa strategier avsevärt förbättra programmets motståndskraft och prestanda, särskilt under hög belastning eller försämrade förhållanden.
Strategi för tröskelvärdesbaserad tillgänglighet
Den tröskelvärdesbaserade tillgänglighetsstrategin kan förbättra svarstiden och tillgängligheten genom att skicka parallella läsbegäranden till sekundära regioner och acceptera det snabbaste svaret. Den här metoden kan drastiskt minska effekten av regionala avbrott eller villkor med långa svarstider för programprestanda. Dessutom kan proaktiv anslutningshantering användas för att ytterligare förbättra prestanda genom att värma upp anslutningar och cacheminnen i både den aktuella läsregionen och önskade fjärrregioner.
Exempelkonfiguration:
// Proactive Connection Management
CosmosContainerIdentity containerIdentity = new CosmosContainerIdentity("sample_db_id", "sample_container_id");
int proactiveConnectionRegionsCount = 2;
Duration aggressiveWarmupDuration = Duration.ofSeconds(1);
CosmosAsyncClient clientWithOpenConnections = new CosmosClientBuilder()
.endpoint("<account URL goes here")
.key("<account key goes here>")
.endpointDiscoveryEnabled(true)
.preferredRegions(Arrays.asList("sample_region_1", "sample_region_2"))
.openConnectionsAndInitCaches(new CosmosContainerProactiveInitConfigBuilder(Arrays.asList(containerIdentity))
.setProactiveConnectionRegionsCount(proactiveConnectionRegionsCount)
//setting aggressive warmup duration helps in cases where there is a high no. of partitions
.setAggressiveWarmupDuration(aggressiveWarmupDuration)
.build())
.directMode()
.buildAsyncClient();
CosmosAsyncContainer container = clientWithOpenConnections.getDatabase("sample_db_id").getContainer("sample_container_id");
int threshold = 500;
int thresholdStep = 100;
CosmosEndToEndOperationLatencyPolicyConfig config = new CosmosEndToEndOperationLatencyPolicyConfigBuilder(Duration.ofSeconds(3))
.availabilityStrategy(new ThresholdBasedAvailabilityStrategy(Duration.ofMillis(threshold), Duration.ofMillis(thresholdStep)))
.build();
CosmosItemRequestOptions options = new CosmosItemRequestOptions();
options.setCosmosEndToEndOperationLatencyPolicyConfig(config);
container.readItem("id", new PartitionKey("pk"), options, JsonNode.class).block();
// Write operations can benefit from threshold-based availability strategy if opted into non-idempotent write retry policy
// and the account is configured for multi-region writes.
options.setNonIdempotentWriteRetryPolicy(true, true);
container.createItem("id", new PartitionKey("pk"), options, JsonNode.class).block();
Så här fungerar det:
Inledande begäran: Vid tidpunkten T1 görs en läsbegäran till den primära regionen (till exempel USA, östra). SDK väntar på ett svar på upp till 500 millisekunder (värdet
threshold
).Andra begäran: Om det inte finns något svar från den primära regionen inom 500 millisekunder skickas en parallell begäran till nästa prioriterade region (till exempel USA, östra 2).
Tredje begäran: Om varken den primära eller den sekundära regionen svarar inom 600 millisekunder (500 ms + 100 ms,
thresholdStep
värdet) skickar SDK en annan parallell begäran till den tredje föredragna regionen (till exempel USA, västra).Snabbaste svar vinner: Den region som svarar först, det svaret accepteras och de andra parallella begärandena ignoreras.
Proaktiv anslutningshantering hjälper till genom att värma upp anslutningar och cacheminnen för containrar i de önskade regionerna, vilket minskar svarstiden för kallstart för redundansscenarier eller skrivningar i installationer i flera regioner.
Den här strategin kan avsevärt förbättra svarstiden i scenarier där en viss region är långsam eller tillfälligt otillgänglig, men det kan medföra mer kostnader när det gäller enheter för begäranden när parallella begäranden mellan regioner krävs.
Kommentar
Om den första önskade regionen returnerar en icke-tillfällig felstatuskod (t.ex. dokumentet hittades inte, auktoriseringsfel, konflikt osv.) misslyckas själva åtgärden snabbt, eftersom tillgänglighetsstrategin inte skulle ha någon fördel i det här scenariot.
Kretsbrytare på partitionsnivå
Kretsbrytaren på partitionsnivå förbättrar svarstiden och skrivtillgängligheten genom att spåra och kortsluta begäranden till felaktiga fysiska partitioner. Det förbättrar prestanda genom att undvika kända problematiska partitioner och omdirigera begäranden till hälsosammare regioner.
Exempelkonfiguration:
Så här aktiverar du kretsbrytare på partitionsnivå:
System.setProperty(
"COSMOS.PARTITION_LEVEL_CIRCUIT_BREAKER_CONFIG",
"{\"isPartitionLevelCircuitBreakerEnabled\": true, "
+ "\"circuitBreakerType\": \"CONSECUTIVE_EXCEPTION_COUNT_BASED\","
+ "\"consecutiveExceptionCountToleratedForReads\": 10,"
+ "\"consecutiveExceptionCountToleratedForWrites\": 5,"
+ "}");
Så här anger du bakgrundsprocessens frekvens för att kontrollera otillgängliga regioner:
System.setProperty("COSMOS.STALE_PARTITION_UNAVAILABILITY_REFRESH_INTERVAL_IN_SECONDS", "60");
Så här anger du hur länge en partition kan förbli otillgänglig:
System.setProperty("COSMOS.ALLOWED_PARTITION_UNAVAILABILITY_DURATION_IN_SECONDS", "30");
Så här fungerar det:
Spårningsfel: SDK spårar terminalfel (t.ex. 503-, 500-, tidsgränser) för enskilda partitioner i specifika regioner.
Märkning som otillgänglig: Om en partition i en region överskrider ett konfigurerat tröskelvärde för fel markeras den som "Ej tillgänglig". Efterföljande begäranden till den här partitionen kortsluts och omdirigeras till andra hälsosammare regioner.
Automatiserad återställning: En bakgrundstråd kontrollerar regelbundet otillgängliga partitioner. Efter en viss varaktighet markeras dessa partitioner preliminärt som "HealthyTentative" och utsätts för testbegäranden för att verifiera återställningen.
Hälsohöjning/degradering: Baserat på lyckade eller misslyckade testbegäranden höjs partitionens status antingen tillbaka till "Felfri" eller degraderas igen till "Ej tillgänglig".
Den här mekanismen hjälper till att kontinuerligt övervaka partitionens hälsa och ser till att begäranden hanteras med minimal svarstid och maximal tillgänglighet, utan att fastna i problematiska partitioner.
Kommentar
Kretsbrytaren gäller endast för skrivkonton i flera regioner, eftersom när en partition markeras som Unavailable
flyttas både läsningar och skrivningar till nästa önskade region. Detta för att förhindra att läsningar och skrivningar från olika regioner hanteras från samma klientinstans, eftersom detta skulle vara ett antimönster.
Viktigt!
Du måste använda version 4.63.0 av Java SDK eller senare för att kunna aktivera kretsbrytare på partitionsnivå.
Jämföra tillgänglighetsoptimeringar
Strategi för tröskelvärdesbaserad tillgänglighet:
- Fördel: Minskar svarstiden genom att skicka parallella läsbegäranden till sekundära regioner och förbättrar tillgängligheten genom förebyggande begäranden som resulterar i nätverkstimeouter.
- Kompromiss: Medför extra RU-kostnader (enheter för begäranden) jämfört med kretsbrytare, på grund av ytterligare parallella begäranden mellan regioner (men endast under perioder då tröskelvärden överskrids).
- Användningsfall: Optimalt för läsintensiva arbetsbelastningar där det är viktigt att minska svarstiden och en viss extra kostnad (både när det gäller RU-debitering och cpu-belastning för klienten) är acceptabelt. Skrivåtgärder kan också vara till nytta om du väljer en princip för återförsök av icke-idempotent skrivning och kontot har skrivningar i flera regioner.
Kretsbrytare på partitionsnivå:
- Fördel: Förbättrar tillgängligheten och svarstiden genom att undvika partitioner som inte är felfria, vilket säkerställer att begäranden dirigeras till hälsosammare regioner.
- Kompromiss: Medför inte ytterligare RU-kostnader, men kan fortfarande tillåta viss initial tillgänglighetsförlust för begäranden som resulterar i tidsgränser för nätverket.
- Användningsfall: Perfekt för skrivintensiva eller blandade arbetsbelastningar där konsekventa prestanda är viktiga, särskilt när det gäller partitioner som tillfälligt kan bli felaktiga.
Båda strategierna kan användas tillsammans för att förbättra läs- och skrivtillgängligheten och minska svarstiden. Kretsbrytare på partitionsnivå kan hantera en mängd olika tillfälliga felscenarier, inklusive sådana som kan leda till långsamma repliker utan att behöva utföra parallella begäranden. Genom att lägga till en tröskelbaserad tillgänglighetsstrategi minimeras dessutom svarstiden och tillgänglighetsförlusten elimineras om ytterligare RU-kostnader är godtagbara.
Genom att implementera dessa strategier kan utvecklare se till att deras program förblir motståndskraftiga, har höga prestanda och ger en bättre användarupplevelse även under regionala avbrott eller långa svarstider.
Konsekvens för regionomfattande sessioner
Översikt
Mer information om konsekvensinställningar i allmänhet finns i Konsekvensnivåer i Azure Cosmos DB. Java SDK ger en optimering för sessionskonsekvens för skrivkonton i flera regioner genom att tillåta att det är regionomfattande. Detta förbättrar prestandan genom att minska svarstiden för gränsöverskridande replikering genom att minimera återförsök på klientsidan. Detta uppnås genom att hantera sessionstoken på regionnivå i stället för globalt. Om konsekvens i ditt program kan begränsas till ett mindre antal regioner kan du genom att implementera sessionskonsekvens med regionomfattning uppnå bättre prestanda och tillförlitlighet för läs- och skrivåtgärder i konton med flera skrivningar genom att minimera fördröjningar och återförsök för replikering mellan regioner.
Förmåner
- Kortare svarstid: Genom att lokalisera validering av sessionstoken till regionnivå minskar risken för kostsamma korsregionala återförsök.
- Förbättrad prestanda: Minimerar effekten av regional redundans och replikeringsfördröjning, vilket ger högre läs-/skrivkonsekvens och lägre CPU-användning.
- Optimerad resursanvändning: Minskar processor- och nätverkskostnaderna för klientprogram genom att begränsa behovet av återförsök och korsregionala anrop, vilket optimerar resursanvändningen.
- Hög tillgänglighet: Genom att underhålla sessionstoken med regionomfattning kan programmen fortsätta att fungera smidigt även om vissa regioner får högre svarstid eller tillfälliga fel.
- Konsekvensgarantier: Säkerställer att sessionskonsekvensen (läs din skriv- och monotona läsning) uppfylls mer tillförlitligt utan onödiga återförsök.
- Kostnadseffektivitet: Minskar antalet korsregionala anrop, vilket kan sänka kostnaderna för dataöverföringar mellan regioner.
- Skalbarhet: Gör att program kan skalas mer effektivt genom att minska konkurrensen och kostnaderna för att underhålla en global sessionstoken, särskilt i installationer i flera regioner.
Kompromisser
- Ökad minnesanvändning: Bloom-filtret och regionspecifik lagring av sessionstoken kräver ytterligare minne, vilket kan vara ett övervägande för program med begränsade resurser.
- Konfigurationskomplexitet: Finjustering av förväntat infogningsantal och falskt positiv hastighet för bloom-filtret lägger till ett lager av komplexitet i konfigurationsprocessen.
- Potential för falska positiva identifieringar: Även om bloom-filtret minimerar korsregionala återförsök finns det fortfarande en liten risk för falska positiva identifieringar som påverkar valideringen av sessionstoken, även om frekvensen kan kontrolleras. En falsk positiv identifiering innebär att den globala sessionstoken har lösts, vilket ökar risken för korsregionala återförsök om den lokala regionen inte har kommit ikapp den här globala sessionen. Sessionsgarantier uppfylls även i närvaro av falska positiva identifieringar.
- Tillämplighet: Den här funktionen är mest fördelaktig för program med hög kardinalitet för logiska partitioner och regelbundna omstarter. Program med färre logiska partitioner eller ovanliga omstarter kanske inte ser några större fördelar.
Hur det fungerar
Ange sessionstoken
- Slutförande av begäran: När en begäran har slutförts samlar SDK in sessionstoken och associerar den med regionen och partitionsnyckeln.
- Lagring på regionnivå: Sessionstoken lagras i en kapslad
ConcurrentHashMap
som underhåller mappningar mellan partitionsnyckelintervall och förlopp på regionnivå. - Bloom Filter: Ett blomfilter håller reda på vilka regioner som har använts av varje logisk partition, vilket hjälper till att lokalisera validering av sessionstoken.
Lösa sessionstoken
- Initiering av begäran: Innan en begäran skickas försöker SDK:t matcha sessionstoken för lämplig region.
- Tokenkontroll: Token kontrolleras mot regionspecifika data för att säkerställa att begäran dirigeras till den senaste repliken.
- Logik för återförsök: Om sessionstoken inte verifieras i den aktuella regionen försöker SDK:n igen med andra regioner, men med tanke på den lokaliserade lagringen är detta mindre vanligt.
Använda SDK
Så här initierar du CosmosClient med sessionskonsekvens med regionomfattning:
CosmosClient client = new CosmosClientBuilder()
.endpoint("<your-endpoint>")
.key("<your-key>")
.consistencyLevel(ConsistencyLevel.SESSION)
.buildClient();
// Your operations here
Aktivera konsekvens för sessioner med regionomfattning
Ange följande systemegenskap för att aktivera sessionsinfångning med regionomfattning i ditt program:
System.setProperty("COSMOS.SESSION_CAPTURING_TYPE", "REGION_SCOPED");
Konfigurera bloom-filter
Finjustera prestandan genom att konfigurera förväntade infogningar och falsk positiv frekvens för blomfiltret:
System.setProperty("COSMOS.PK_BASED_BLOOM_FILTER_EXPECTED_INSERTION_COUNT", "5000000"); // adjust as needed
System.setProperty("COSMOS.PK_BASED_BLOOM_FILTER_EXPECTED_FFP_RATE", "0.001"); // adjust as needed
System.setProperty("COSMOS.SESSION_CAPTURING_TYPE", "REGION_SCOPED");
System.setProperty("COSMOS.PK_BASED_BLOOM_FILTER_EXPECTED_INSERTION_COUNT", "1000000");
System.setProperty("COSMOS.PK_BASED_BLOOM_FILTER_EXPECTED_FFP_RATE", "0.01");
Minneskonsekvenser
Nedan visas den behållna storleken (storleken på objektet och vad det beror på) för den interna sessionscontainern (som hanteras av SDK:et) med varierande förväntade infogningar i bloom-filtret.
Förväntade infogningar | Falsk positiv frekvens | Behållen storlek |
---|---|---|
10, 000 | 0,001 | 21 KB |
100, 000 | 0,001 | 183 KB |
1 miljon | 0,001 | 1,8 MB |
10 miljoner | 0,001 | 17,9 MB |
100 miljoner | 0,001 | 179 MB |
1 miljard | 0,001 | 1,8 GB |
Viktigt!
Du måste använda version 4.60.0 av Java SDK eller senare för att aktivera sessionskonsekvens med regionomfattning.
Justera konfiguration av direkt- och gatewayanslutning
Information om hur du optimerar anslutningskonfigurationer för direkt- och gatewayläge finns i hur du justerar anslutningskonfigurationer för Java SDK v4.
SDK-användning
- Installera den senaste SDK:en
Azure Cosmos DB SDK:er förbättras ständigt för att ge bästa möjliga prestanda. Information om de senaste SDK-förbättringarna finns i Azure Cosmos DB SDK.
Varje Azure Cosmos DB-klientinstans är trådsäker och utför effektiv anslutningshantering och adresscachelagring. För att möjliggöra effektiv anslutningshantering och bättre prestanda för Azure Cosmos DB-klienten rekommenderar vi starkt att du använder en enda instans av Azure Cosmos DB-klienten under programmets livslängd.
När du skapar en CosmosClient är standardkonsekvensen som används om den inte uttryckligen anges Sessions. Om sessionskonsekvens inte krävs av din programlogik anger du Konsekvens till Slutlig. Obs! Vi rekommenderar att du använder sessionskonsekvens i program som använder Azure Cosmos DB-ändringsflödesprocessorn.
- Använd Async API för att maximera etablerat dataflöde
Azure Cosmos DB Java SDK v4 paketer två API:er: Sync och Async. Async-API:et implementerar I stort sett SDK-funktioner, medan Synkroniserings-API:et är en tunn omslutning som gör blockeringsanrop till Async-API:et. Detta står i kontrast till den äldre Azure Cosmos DB Async Java SDK v2, som endast var Async, och till den äldre Azure Cosmos DB Sync Java SDK v2, som var Endast synkronisering och hade en separat implementering.
Valet av API bestäms under klientinitieringen. en CosmosAsyncClient stöder Async API medan en CosmosClient stöder Synkroniserings-API.
Async-API:et implementerar icke-blockerande I/O och är det optimala valet om ditt mål är att maximera dataflödet när du skickar begäranden till Azure Cosmos DB.
Att använda Synkroniserings-API kan vara rätt val om du vill ha eller behöver ett API, som blockerar svaret på varje begäran, eller om synkron åtgärd är det dominerande paradigmet i ditt program. Du kanske till exempel vill ha synkroniserings-API:et när du bevarar data till Azure Cosmos DB i ett mikrotjänstprogram, förutsatt att dataflödet inte är kritiskt.
Observera att api-dataflödet för synkronisering försämras med ökad svarstid för begäran, medan Async-API:et kan mätta maskinvarans fullständiga bandbreddsfunktioner.
Geografisk sortering kan ge dig högre och mer konsekvent dataflöde när du använder Sync API (se Sortera klienter i samma Azure-region för prestanda) men förväntas fortfarande inte överskrida Async API-uppnåeligt dataflöde.
Vissa användare kanske inte heller känner till Project Reactor, det reaktiva Streams-ramverket som används för att implementera Azure Cosmos DB Java SDK v4 Async API. Om detta är ett problem rekommenderar vi att du läser vår introduktionsguide för reaktormönster och sedan tar en titt på den här introduktionen till reaktiv programmering för att bekanta dig. Om du redan har använt Azure Cosmos DB med ett Async-gränssnitt och SDK:t du använde var Azure Cosmos DB Async Java SDK v2, kanske du är bekant med ReactiveX/RxJava men är osäker på vad som har ändrats i Project Reactor. I så fall kan du ta en titt på vår reactor vs. RxJava Guide för att bekanta dig.
Följande kodfragment visar hur du initierar din Azure Cosmos DB-klient för Async API- eller Sync API-åtgärd:
Java SDK V4 (Maven com.azure::azure-cosmos) Async API
CosmosAsyncClient client = new CosmosClientBuilder()
.endpoint(HOSTNAME)
.key(MASTERKEY)
.consistencyLevel(CONSISTENCY)
.buildAsyncClient();
- Skala ut din klientarbetsbelastning
Om du testar på höga dataflödesnivåer kan klientprogrammet bli flaskhalsen på grund av att datorn begränsar processor- eller nätverksanvändningen. Om du når den här punkten kan du fortsätta att push-överföra Azure Cosmos DB-kontot ytterligare genom att skala ut dina klientprogram över flera servrar.
En bra tumregel är att inte överskrida >50 % processoranvändning på en viss server för att hålla svarstiden låg.
- Använd Lämplig Scheduler (Undvik att stjäla IO Netty-trådar i händelseloopen)
Asynkrona funktioner i Azure Cosmos DB Java SDK baseras på netty icke-blockerande I/O. SDK:n använder ett fast antal I/O Netty-händelselooptrådar (så många processorkärnor som datorn har) för att köra I/O-åtgärder. Flux som returneras av API:et visar resultatet på en av den delade I/O-händelseloopens Netty-trådar. Därför är det viktigt att du inte blockerar den delade I/O-händelseloopens Netty-trådar. Att utföra processorintensivt arbete eller blockera åtgärder i I/O-händelseloopens nättråd kan orsaka dödläge eller avsevärt minska SDK-dataflödet.
Följande kod kör till exempel ett processorintensivt arbete på händelseloopens I/O netty-tråd:
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();
});
När resultatet har tagits emot bör du undvika att utföra processorintensivt arbete med resultatet på händelseloopens IO netty-tråd. Du kan i stället ange en egen Scheduler för att tillhandahålla en egen tråd för att köra ditt arbete, enligt nedan (kräver 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();
});
Baserat på typen av arbete bör du använda lämplig befintlig reaktorschemaläggare för ditt arbete. Läs här Schedulers
.
Mer information om trådnings- och schemaläggningsmodellen för projektet Reactor finns i det här blogginlägget från Project Reactor.
Mer information om Azure Cosmos DB Java SDK v4 finns i Azure Cosmos DB-katalogen för Azure SDK för Java-monorepo på GitHub.
- Optimera loggningsinställningarna i ditt program
Av olika skäl bör du lägga till loggning i en tråd som genererar högt dataflöde för begäranden. Om målet är att helt mätta en containers etablerade dataflöde med begäranden som genereras av den här tråden kan loggningsoptimeringar avsevärt förbättra prestandan.
- Konfigurera en asynkron loggare
Svarstiden för en synkron logger påverkar nödvändigtvis den övergripande svarstidsberäkningen för din begärangenererande tråd. En asynkron loggare som log4j2 rekommenderas för att frikoppla loggningskostnaderna från dina programtrådar med höga prestanda.
- Inaktivera nettys loggning
Netty-biblioteksloggning är pratsam och måste stängas av (det räcker kanske inte att ignorera inloggningen i konfigurationen) för att undvika ytterligare CPU-kostnader. Om du inte är i felsökningsläge inaktiverar du nettys loggning helt och hållet. Så om du använder Log4j för att ta bort de ytterligare CPU-kostnader som uppstår org.apache.log4j.Category.callAppenders()
från netty lägger du till följande rad i din kodbas:
org.apache.log4j.Logger.getLogger("io.netty").setLevel(org.apache.log4j.Level.OFF);
- Resursgräns för öppna OS-filer
Vissa Linux-system (till exempel Red Hat) har en övre gräns för antalet öppna filer och därmed det totala antalet anslutningar. Kör följande för att visa de aktuella gränserna:
ulimit -a
Antalet öppna filer (nofile
) måste vara tillräckligt stort för att ha tillräckligt med utrymme för din konfigurerade storlek på anslutningspoolen och andra öppna filer i operativsystemet. Den kan ändras för att tillåta en större storlek på anslutningspoolen.
Öppna filen limits.conf:
vim /etc/security/limits.conf
Lägg till/ändra följande rader:
* - nofile 100000
- Ange partitionsnyckel i punktskrivningar
För att förbättra prestanda för punktskrivningar anger du objektpartitionsnyckeln i API-anropet för punktskrivning enligt nedan:
Java SDK V4 (Maven com.azure::azure-cosmos) Async API
asyncContainer.createItem(item,new PartitionKey(pk),new CosmosItemRequestOptions()).block();
I stället för att bara tillhandahålla objektinstansen, som visas nedan:
Java SDK V4 (Maven com.azure::azure-cosmos) Async API
asyncContainer.createItem(item).block();
Det senare stöds men lägger till svarstider i ditt program. SDK:et måste parsa objektet och extrahera partitionsnyckeln.
Frågeåtgärder
Information om frågeåtgärder finns i prestandatipsen för frågor.
Indexeringsprincip
- Utesluta sökvägar som inte används från indexering för att få snabbare skrivning
Med Azure Cosmos DB:s indexeringsprincip kan du ange vilka dokumentsökvägar som ska inkluderas eller undantas från indexering med hjälp av Indexeringssökvägar (setIncludedPaths och setExcludedPaths). Användningen av indexeringssökvägar kan ge bättre skrivprestanda och lägre indexlagring för scenarier där frågemönstren är kända i förväg, eftersom indexeringskostnaderna är direkt korrelerade med antalet indexerade unika sökvägar. Följande kod visar till exempel hur du inkluderar och exkluderar hela delar av dokumenten (kallas även för ett underträd) från indexering med jokertecknet "*".
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);
Mer information finns i Azure Cosmos DB-indexeringsprinciper.
Genomflöde
- Mät och justera för lägre användning av enheter för begäranden/sekund
Azure Cosmos DB erbjuder en omfattande uppsättning databasåtgärder, inklusive relationsfrågor och hierarkiska frågor med UDF:er, lagrade procedurer och utlösare – som alla körs på dokumenten i en databassamling. Den kostnad som hör till var och en av dessa operationer varierar baserat på vilken CPU, vilka IO-resurser och hur mycket minne som krävs för att slutföra operationen. I stället för att tänka på och hantera maskinvaruresurser kan du betrakta en enhet för begäran (RU) som ett enda mått för de resurser som krävs för att utföra olika databasåtgärder och hantera en programbegäran.
Dataflödet etableras baserat på antalet enheter för begäranden som angetts för varje container. Enhetsförbrukning för begäran utvärderas som en hastighet per sekund. Program som överskrider den etablerade enhetsfrekvensen för begäranden för containern begränsas tills priset sjunker under den etablerade nivån för containern. Om programmet kräver ett högre dataflöde kan du öka dataflödet genom att etablera ytterligare enheter för begäranden.
Komplexiteten i en fråga påverkar hur många enheter för begäran som förbrukas för en åtgärd. Antalet predikat, predikatens natur, antalet UDF:er och storleken på källdatauppsättningen påverkar alla kostnaden för frågeåtgärder.
Om du vill mäta omkostnaderna för en åtgärd (skapa, uppdatera eller ta bort) kontrollerar du rubriken x-ms-request-charge för att mäta antalet enheter för begäranden som förbrukas av dessa åtgärder. Du kan också titta på motsvarande RequestCharge-egenskap i ResourceResponse<T> eller FeedResponse<T>.
Java SDK V4 (Maven com.azure::azure-cosmos) Async API
CosmosItemResponse<CustomPOJO> response = asyncContainer.createItem(item).block();
response.getRequestCharge();
Den begärandeavgift som returneras i det här huvudet är en bråkdel av ditt etablerade dataflöde. Om du till exempel har etablerat 2 000 RU/s och om föregående fråga returnerar 1 000 1 KB-dokument är kostnaden för åtgärden 1 000. Därför respekterar servern bara två sådana begäranden inom en sekund innan efterföljande begäranden begränsas. Mer information finns i Enheter för begäran och kalkylatorn för begärandeenheten.
- Hantera hastighetsbegränsning/begärandefrekvens för stor
När en klient försöker överskrida det reserverade dataflödet för ett konto sker ingen prestandaförsämring på servern och ingen användning av dataflödeskapacitet utöver den reserverade nivån. Servern avslutar begäran i förebyggande syfte med RequestRateTooLarge (HTTP-statuskod 429) och returnerar rubriken x-ms-retry-after-ms som anger hur lång tid, i millisekunder, som användaren måste vänta innan begäran försöker igen.
HTTP Status 429,
Status Line: RequestRateTooLarge
x-ms-retry-after-ms :100
SDK:erna fångar alla implicit det här svaret, respekterar det server-angivna återförsökshuvudet och försöker begära igen. Om inte ditt konto används samtidigt av flera klienter kommer nästa återförsök att lyckas.
Om du har fler än en klient som kumulativt fungerar konsekvent över begärandefrekvensen kanske standardantalet för återförsök som för närvarande är inställt på 9 internt av klienten kanske inte räcker. I det här fallet genererar klienten en CosmosClientException med statuskod 429 till programmet. Standardantalet för återförsök kan ändras med hjälp setMaxRetryAttemptsOnThrottledRequests()
av instansen ThrottlingRetryOptions
. Som standard returneras CosmosClientException med statuskod 429 efter en kumulativ väntetid på 30 sekunder om begäran fortsätter att fungera över begärandefrekvensen. Detta inträffar även om det aktuella antalet återförsök är mindre än det maximala antalet återförsök, oavsett om det är standardvärdet 9 eller ett användardefinierat värde.
Även om det automatiserade återförsöksbeteendet hjälper till att förbättra återhämtning och användbarhet för de flesta program, kan det komma till odds när prestandamått utförs, särskilt när svarstiden mäts. Den klient observerade svarstiden ökar om experimentet når serverbegränsningen och gör att klient-SDK:t tyst försöker igen. För att undvika svarstidstoppar under prestandaexperiment mäter du den avgift som returneras av varje åtgärd och ser till att begäranden fungerar under den reserverade begärandefrekvensen. Mer information finns i Enheter för begäran.
- Designa för mindre dokument för högre dataflöde
Begärandeavgiften (kostnaden för bearbetning av begäran) för en viss åtgärd är direkt korrelerad till dokumentets storlek. Åtgärder på stora dokument kostar mer än åtgärder för små dokument. Vi rekommenderar att du utformar ditt program och arbetsflöden så att objektstorleken är ~1 KB, eller liknande ordning eller storlek. För svarstidskänsliga program bör stora objekt undvikas – dokument med flera MB gör programmet långsammare.
Nästa steg
Mer information om hur du utformar ditt program för skalning och höga prestanda finns i Partitionering och skalning i Azure Cosmos DB.
Försöker du planera kapacitet för en migrering till Azure Cosmos DB? Du kan använda information om ditt befintliga databaskluster för kapacitetsplanering.
- Om allt du vet är antalet virtuella kärnor och servrar i ditt befintliga databaskluster läser du om att uppskatta enheter för begäranden med virtuella kärnor eller virtuella kärnor
- Om du känner till vanliga begärandefrekvenser för din aktuella databasarbetsbelastning kan du läsa om att uppskatta enheter för begäranden med azure Cosmos DB-kapacitetshanteraren