Diagnostika a řešení potíží s pomalými požadavky v sadě .NET SDK služby Azure Cosmos DB
PLATÍ PRO: NoSQL
Ve službě Azure Cosmos DB si můžete všimnout pomalých požadavků. Zpoždění můžou nastat z několika důvodů, jako je omezování požadavků nebo způsob, jakým je vaše aplikace navržená. Tento článek vysvětluje různé původní příčiny tohoto problému.
Příliš vysoká frekvence požadavků
Omezování požadavků je nejčastějším důvodem pomalých požadavků. Azure Cosmos DB omezuje požadavky, pokud překročí přidělené jednotky žádostí pro databázi nebo kontejner. Sada SDK má integrovanou logiku pro opakování těchto požadavků. Článek o řešení potíží s příliš velkou rychlostí požadavků vysvětluje, jak zkontrolovat, jestli dochází k omezování požadavků. Tento článek také popisuje, jak v budoucnu škálovat účet, aby se těmto problémům vyhnul.
Návrh aplikací
Při návrhu aplikace postupujte podle osvědčených postupů sady .NET SDK pro dosažení nejlepšího výkonu. Pokud vaše aplikace nedodržuje osvědčené postupy sady SDK, můžou se vám zobrazit pomalé nebo neúspěšné požadavky.
Při vývoji aplikace zvažte následující skutečnosti:
- Aplikace by měla být ve stejné oblasti jako váš účet služby Azure Cosmos DB.
- Oblasti ApplicationRegion nebo ApplicationPreferredRegions by měly odrážet vaši místní předvolbu a odkazovat na oblast, ve které je vaše aplikace nasazená.
- Kvůli vysokému provozu může na síťovém rozhraní dojít k kritickým bodům. Pokud je aplikace spuštěná ve službě Azure Virtual Machines, existují možná alternativní řešení:
- Zvažte použití virtuálního počítače s povolenými akcelerovanými síťovými službami.
- Povolte akcelerované síťové služby na existujícím virtuálním počítači.
- Zvažte použití virtuálního počítače vyššího typu.
- Preferujete režim přímého připojení.
- Vyhněte se vysokému využití procesoru. Nezapomeňte se podívat na maximální využití procesoru a ne na průměr, což je výchozí hodnota pro většinu systémů protokolování. Latence může zvýšit cokoli nad přibližně 40 procenty.
Operace s metadaty
Pokud potřebujete ověřit, že databáze nebo kontejner existuje, neprovádíte to voláním Create...IfNotExistsAsync
nebo Read...Async
před provedením operace položky. Ověření by se mělo provést pouze při spuštění aplikace, pokud je to nutné, pokud očekáváte, že se odstraní. Tyto operace s metadaty generují dodatečnou latenci, nemají smlouvu o úrovni služeb (SLA) a mají svá vlastní samostatná omezení. Nedají se škálovat jako datové operace.
Pomalé požadavky v hromadném režimu
Hromadný režim je režim optimalizovaný pro propustnost, který je určený pro operace s velkým objemem dat, nikoli režim optimalizovaný pro latenci. Je určený k nasycení dostupné propustnosti. Pokud při použití hromadného režimu dochází k pomalým požadavkům, ujistěte se, že:
- Vaše aplikace se kompiluje v konfiguraci vydané verze.
- Při ladění aplikace neměříte latenci (nejsou připojeny žádné ladicí programy).
- Objem operací je vysoký, nepoužívejte hromadně pro méně než 1 000 operací. Zřízená propustnost určuje, kolik operací za sekundu můžete zpracovat, vaším cílem by hromadné využití bylo co nejvíce.
- Monitorujte kontejner pro scénáře omezování. Pokud se kontejner výrazně omezuje, znamená to, že objem dat je větší než zřízená propustnost, musíte buď vertikálně navýšit kapacitu kontejneru, nebo snížit objem dat (možná vytvořit menší dávky dat najednou).
- Model správně používáte
async/await
ke zpracování všech souběžných úloh a neblokujete žádnou asynchronní operaci.
Zachytávání diagnostiky
Všechny odpovědi v sadě SDK, včetně CosmosException
, mají Diagnostics
vlastnost. Tato vlastnost zaznamenává všechny informace související s jedním požadavkem, včetně toho, jestli došlo k opakovaným pokusům nebo přechodným selháním.
Diagnostika se vrátí jako řetězec. Řetězec se mění s každou verzí, protože se vylepšuje pro řešení potíží s různými scénáři. U každé verze sady SDK bude řetězec obsahovat zásadní změny formátování. Řetězec neza parsujte, abyste se vyhnuli zásadním změnám. Následující ukázka kódu ukazuje, jak číst diagnostické protokoly pomocí sady .NET SDK:
try
{
ItemResponse<Book> response = await this.Container.CreateItemAsync<Book>(item: testItem);
if (response.Diagnostics.GetClientElapsedTime() > ConfigurableSlowRequestTimeSpan)
{
// Log the response.Diagnostics.ToString() and add any additional info necessary to correlate to other logs
}
}
catch (CosmosException cosmosException)
{
// Log the full exception including the stack trace with: cosmosException.ToString()
// The Diagnostics can be logged separately if required with: cosmosException.Diagnostics.ToString()
}
// When using Stream APIs
ResponseMessage response = await this.Container.CreateItemStreamAsync(partitionKey, stream);
if (response.Diagnostics.GetClientElapsedTime() > ConfigurableSlowRequestTimeSpan || !response.IsSuccessStatusCode)
{
// Log the diagnostics and add any additional info necessary to correlate to other logs with: response.Diagnostics.ToString()
}
Diagnostika ve verzi 3.19 a novější
Struktura JSON obsahuje zásadní změny v každé verzi sady SDK. To zneschváňuje analýzu. JSON představuje stromovou strukturu požadavku procházející sadou SDK. V následujících částech najdete několik klíčových věcí, na které se můžete podívat.
Historie procesoru
Nejčastější příčinou nízkých požadavků je vysoké využití procesoru. Pro zajištění optimální latence by využití procesoru mělo být přibližně 40 %. K monitorování maximálního (ne průměrného) využití procesoru použijte interval 10 sekund. Špičky procesoru jsou častější u dotazů napříč oddíly, kdy požadavky můžou pro jeden dotaz provádět více připojení.
Mezi časové limity patří diagnostika, která obsahuje následující:
"systemHistory": [
{
"dateUtc": "2021-11-17T23:38:28.3115496Z",
"cpu": 16.731,
"memory": 9024120.000,
"threadInfo": {
"isThreadStarving": "False",
....
}
},
{
"dateUtc": "2021-11-17T23:38:38.3115496Z",
"cpu": 16.731,
"memory": 9024120.000,
"threadInfo": {
"isThreadStarving": "False",
....
}
},
...
]
cpu
Pokud jsou hodnoty větší než 70 procent, časový limit bude pravděpodobně způsoben vyčerpáním procesoru. V takovém případě je řešením zjistit zdroj vysokého využití procesoru a snížit toto využití nebo škálovat počítač na větší velikost prostředků.threadInfo/isThreadStarving
Pokud uzly majíTrue
hodnoty, příčinou je hladovění vlákna. V tomto případě je řešením prozkoumat zdroj nebo zdroje hladovění vlákna (potenciálně uzamčená vlákna) nebo škálovat počítač nebo počítače na větší velikost prostředku.dateUtc
Pokud doba mezi měřeními není přibližně 10 sekund, znamená to také kolize ve fondu vláken. Procesor se měří jako nezávislá úloha, která se každých 10 sekund zařidí do fronty ve fondu vláken. Pokud je doba mezi měřeními delší, znamená to, že asynchronní úlohy se nedají včas zpracovat. Nejběžnějším scénářem je, že kód aplikace blokuje volání přes asynchronní kód.
Řešení
Klientské aplikaci, která používá sadu SDK, by měla být vertikálně navýšena kapacita nebo by se měla škálovat na více instancí.
HttpResponseStats
HttpResponseStats
jsou požadavky, které přejdou na bránu. I v přímém režimu získá sada SDK všechny informace o metadatech z brány.
Pokud je požadavek pomalý, nejprve ověřte, že žádný z předchozích návrhů nevyvolá požadované výsledky. Pokud je stále pomalý, různé vzory ukazují na různé problémy. Další podrobnosti najdete v následující tabulce.
Počet žádostí | Scénář | Popis |
---|---|---|
Jedno pro všechny | Časový limit požadavku nebo HttpRequestExceptions |
Odkazuje na vyčerpání portů SNAT nebo nedostatek prostředků na počítači pro zpracování požadavku v čase. |
Jedno nebo malé procento (smlouva SLA není porušená) | Všechny | Jedno nebo malé procento pomalých požadavků může být způsobeno několika různými přechodnými problémy a mělo by se očekávat. |
Vše | Vše | Odkazuje na problém s infrastrukturou nebo sítí. |
Smlouva SLA byla porušena. | Neprošly žádné změny aplikace a smlouva SLA se zrušila. | Odkazuje na problém se službou Azure Cosmos DB. |
"HttpResponseStats": [
{
"StartTimeUTC": "2021-06-15T13:53:09.7961124Z",
"EndTimeUTC": "2021-06-15T13:53:09.7961127Z",
"RequestUri": "https://127.0.0.1:8081/dbs/347a8e44-a550-493e-88ee-29a19c070ecc/colls/4f72e752-fa91-455a-82c1-bf253a5a3c4e",
"ResourceType": "Collection",
"HttpMethod": "GET",
"ActivityId": "e16e98ec-f2e3-430c-b9e9-7d99e58a4f72",
"StatusCode": "OK"
}
]
StoreResult
StoreResult
představuje jeden požadavek na službu Azure Cosmos DB pomocí přímého režimu s protokolem TCP.
Pokud je stále pomalý, různé vzory ukazují na různé problémy. Další podrobnosti najdete v následující tabulce.
Počet žádostí | Scénář | Popis |
---|---|---|
Jedno pro všechny | StoreResult obsahuje TransportException |
Odkazuje na vyčerpání portů SNAT nebo nedostatek prostředků na počítači pro zpracování požadavku v čase. |
Jedno nebo malé procento (smlouva SLA není porušená) | Všechny | Jedno nebo malé procento pomalých požadavků může být způsobeno několika různými přechodnými problémy a mělo by se očekávat. |
Vše | Vše | Problém s infrastrukturou nebo sítí |
Smlouva SLA byla porušena. | Požadavky obsahují více kódů chyb selhání, například 410 |
Odkazuje na problém se službou Azure Cosmos DB nebo klientským počítačem. |
Smlouva SLA byla porušena. | StorePhysicalAddress jsou stejné, bez stavového kódu selhání. |
Pravděpodobně problém se službou Azure Cosmos DB. |
Smlouva SLA byla porušena. | StorePhysicalAddress mají stejné ID oddílu, ale jiná ID replik bez stavového kódu selhání. |
Pravděpodobně problém se službou Azure Cosmos DB. |
Smlouva SLA byla porušena. | StorePhysicalAddress je náhodný, bez stavový kód selhání. |
Odkazuje na problém s počítačem. |
U více výsledků úložiště pro jeden požadavek mějte na paměti následující skutečnosti:
- Silná konzistence a konzistence omezené nestarosti vždy mají alespoň dva výsledky úložiště.
- Zkontrolujte stavový kód každého
StoreResult
. Sada SDK se automaticky opakuje v několika různých přechodných selháních. Sada SDK se neustále vylepšuje, aby zahrnovala více scénářů.
RequestTimeline
Umožňuje zobrazit čas pro různé fáze odesílání a přijímání požadavků v přenosové vrstvě.
ChannelAcquisitionStarted
: Čas získání nebo vytvoření nového připojení. Připojení je možné vytvořit z mnoha důvodů, například: Předchozí připojení bylo uzavřeno kvůli nečinnosti pomocí CosmosClientOptions.IdleTcpConnectionTimeout, objem souběžných požadavků překračuje CosmosClientOptions.MaxRequestsPerTcpConnection, připojení bylo ukončeno kvůli chybě sítě nebo aplikace nesleduje vzor Singleton a nové instance se neustále vytvářejí. Po navázání připojení se znovu použije pro následné požadavky, takže by to nemělo mít vliv na latenci P99, pokud se nedějí dříve uvedené problémy.Pipelined
: Doba strávená zápisem požadavku do soketu TCP. Požadavek lze zapsat pouze na soket TCP po jednom, velká hodnota označuje kritický bod na soketu TCP, který je běžně přidružen k uzamčeným vláknům kódem aplikace nebo velkou velikostí požadavků.Transit time
: Čas strávený v síti po napsání požadavku na soket TCP. Porovnejte toto číslo s číslemBELatencyInMs
. PokudBELatencyInMs
je malý, pak byl čas strávený v síti, a ne ve službě Azure Cosmos DB. Pokud požadavek selhal s vypršením časového limitu, znamená to, jak dlouho klient čekal bez odpovědi, a zdroj je latence sítě.Received
: Doba mezi odezvou byla přijata a zpracována sadou SDK. Velká hodnota je obvykle způsobena hladověním vlákna nebo uzamčenými vlákny.
ServiceEndpointStatistics
Informace o konkrétním back-endovém serveru Sada SDK může otevřít více připojení k jednomu back-endovému serveru v závislosti na počtu čekajících požadavků a maxConcurrentRequestsPerConnection.
inflightRequests
Počet čekajících požadavků na back-endový server (možná z různých oddílů). Vysoké číslo může vést k většímu provozu a vyšší latenci.openConnections
je celkový počet připojení otevřených k jednomu back-endovému serveru. To může být užitečné k zobrazení vyčerpání portů SNAT, pokud je toto číslo velmi vysoké.
ConnectionStatistics
Informace o konkrétním připojení (novém nebo starém) požadavku, ke kterému se přiřadí.
waitforConnectionInit
: Aktuální požadavek čekal na dokončení inicializace nového připojení. To povede k vyšší latenci.callsPendingReceive
: Počet volání čekajících na přijetí před odesláním tohoto hovoru. Vysoké číslo nám může ukázat, že před tímto voláním bylo mnoho volání, což může vést k vyšší latenci. Pokud je toto číslo vysoké, odkazuje na problém blokující vedoucí řádek, který může způsobit jiný požadavek, jako je operace dotazu nebo informačního kanálu, která trvá dlouhou dobu zpracování. Zkuste snížit počet kanálů CosmosClientOptions.MaxRequestsPerTcpConnection.LastSentTime
: Čas posledního požadavku odeslaného na tento server. To spolu s lastReceivedTime se dá použít k zobrazení problémů s připojením nebo koncovým bodem. Pokud například existuje mnoho časových limitů příjmu, doba odeslání bude mnohem větší než doba přijetí.lastReceive
: Čas posledního požadavku přijatého z tohoto serverulastSendAttempt
: Čas posledního pokusu o odeslání
Velikosti požadavků a odpovědí
requestSizeInBytes
: Celková velikost požadavku odeslaného do služby Azure Cosmos DBresponseMetadataSizeInBytes
: Velikost hlaviček vrácených ze služby Azure Cosmos DBresponseBodySizeInBytes
: Velikost obsahu vráceného ze služby Azure Cosmos DB
"StoreResult": {
"ActivityId": "bab6ade1-b8de-407f-b89d-fa2138a91284",
"StatusCode": "Ok",
"SubStatusCode": "Unknown",
"LSN": 453362,
"PartitionKeyRangeId": "1",
"GlobalCommittedLSN": 0,
"ItemLSN": 453358,
"UsingLocalLSN": true,
"QuorumAckedLSN": -1,
"SessionToken": "-1#453362",
"CurrentWriteQuorum": -1,
"CurrentReplicaSetSize": -1,
"NumberOfReadRegions": 0,
"IsValid": true,
"StorePhysicalAddress": "rntbd://127.0.0.1:10253/apps/DocDbApp/services/DocDbServer92/partitions/a4cb49a8-38c8-11e6-8106-8cdcd42c33be/replicas/1s/",
"RequestCharge": 1,
"RetryAfterInMs": null,
"BELatencyInMs": "0.304",
"transportRequestTimeline": {
"requestTimeline": [
{
"event": "Created",
"startTimeUtc": "2022-05-25T12:03:36.3081190Z",
"durationInMs": 0.0024
},
{
"event": "ChannelAcquisitionStarted",
"startTimeUtc": "2022-05-25T12:03:36.3081214Z",
"durationInMs": 0.0132
},
{
"event": "Pipelined",
"startTimeUtc": "2022-05-25T12:03:36.3081346Z",
"durationInMs": 0.0865
},
{
"event": "Transit Time",
"startTimeUtc": "2022-05-25T12:03:36.3082211Z",
"durationInMs": 1.3324
},
{
"event": "Received",
"startTimeUtc": "2022-05-25T12:03:36.3095535Z",
"durationInMs": 12.6128
},
{
"event": "Completed",
"startTimeUtc": "2022-05-25T12:03:36.8621663Z",
"durationInMs": 0
}
],
"serviceEndpointStats": {
"inflightRequests": 1,
"openConnections": 1
},
"connectionStats": {
"waitforConnectionInit": "False",
"callsPendingReceive": 0,
"lastSendAttempt": "2022-05-25T12:03:34.0222760Z",
"lastSend": "2022-05-25T12:03:34.0223280Z",
"lastReceive": "2022-05-25T12:03:34.0257728Z"
},
"requestSizeInBytes": 447,
"responseMetadataSizeInBytes": 438,
"responseBodySizeInBytes": 604
},
"TransportException": null
}
Míra selhání porušuje smlouvu SLA služby Azure Cosmos DB
Kontaktní podpora Azure.
Další kroky
- Diagnostika a řešení potíží při použití sady .NET SDK služby Azure Cosmos DB
- Přečtěte si informace o pokynech k výkonu pro sadu .NET SDK.
- Seznamte se s osvědčenými postupy pro sadu .NET SDK.