Diagnozowanie i rozwiązywanie problemów z powolnymi żądaniami w zestawie SDK platformy .NET usługi Azure Cosmos DB
DOTYCZY: NoSQL
W usłudze Azure Cosmos DB możesz zauważyć powolne żądania. Opóźnienia mogą wystąpić z wielu powodów, takich jak ograniczanie żądań lub sposób projektowania aplikacji. W tym artykule wyjaśniono różne główne przyczyny tego problemu.
Zbyt duża liczba żądań
Ograniczanie żądań jest najczęstszą przyczyną wolnych żądań. Usługa Azure Cosmos DB ogranicza żądania, jeśli przekraczają przydzielone jednostki żądania dla bazy danych lub kontenera. Zestaw SDK ma wbudowaną logikę, aby ponowić próby tych żądań. W artykule dotyczącym rozwiązywania problemów zbyt duży współczynnik żądań wyjaśniono, jak sprawdzić, czy żądania są ograniczane. W tym artykule omówiono również sposób skalowania konta w celu uniknięcia tych problemów w przyszłości.
Projekt aplikacji
Podczas projektowania aplikacji postępuj zgodnie z najlepszymi rozwiązaniami dotyczącymi zestawu SDK platformy .NET , aby uzyskać najlepszą wydajność. Jeśli aplikacja nie stosuje najlepszych rozwiązań dotyczących zestawu SDK, żądania mogą być powolne lub nieudane.
Podczas tworzenia aplikacji należy wziąć pod uwagę następujące kwestie:
- Aplikacja powinna znajdować się w tym samym regionie co konto usługi Azure Cosmos DB.
- Region aplikacji lub Region aplikacjiPreferredRegions powinien odzwierciedlać preferencje regionalne i wskazywać region, w którym jest wdrożona aplikacja.
- Może istnieć wąskie gardło interfejsu sieciowego z powodu dużego ruchu. Jeśli aplikacja jest uruchomiona na platformie Azure Virtual Machines, istnieją możliwe obejścia:
- Rozważ użycie maszyny wirtualnej z włączoną przyspieszoną siecią.
- Włącz przyspieszoną sieć na istniejącej maszynie wirtualnej.
- Rozważ użycie wyższej maszyny wirtualnej.
- Preferuj tryb łączności bezpośredniej.
- Unikaj wysokiego użycia procesora CPU. Pamiętaj, aby przyjrzeć się maksymalnemu procesorowi CPU, a nie średniej, czyli domyślnej dla większości systemów rejestrowania. Wszystkie elementy powyżej około 40 procent mogą zwiększyć opóźnienie.
Operacje metadanych
Jeśli musisz sprawdzić, czy baza danych lub kontener istnieje, nie należy tego robić przez wywołanie Create...IfNotExistsAsync
ani Read...Async
przed wykonaniem operacji elementu. Walidacja powinna być wykonywana tylko podczas uruchamiania aplikacji, jeśli jest to konieczne, jeśli spodziewasz się ich usunięcia. Te operacje metadanych generują dodatkowe opóźnienia, nie mają umowy dotyczącej poziomu usług (SLA) i mają własne oddzielne ograniczenia. Nie są one skalowane w taki sposób, jak operacje na danych.
Powolne żądania w trybie zbiorczym
Tryb zbiorczy jest trybem zoptymalizowanym pod kątem przepływności przeznaczonym dla operacji o dużej ilości danych, a nie w trybie zoptymalizowanym pod kątem opóźnienia; ma na celu nasycenie dostępnej przepływności. Jeśli podczas korzystania z trybu zbiorczego występują powolne żądania, upewnij się, że:
- Aplikacja jest kompilowana w konfiguracji wydania.
- Nie mierzysz opóźnienia podczas debugowania aplikacji (bez dołączonych debugerów).
- Ilość operacji jest duża, nie używaj zbiorczo dla mniej niż 1000 operacji. Aprowizowana przepływność określa liczbę operacji na sekundę, które można przetworzyć, a twoim celem jest zbiorcze wykorzystanie jak największej ilości operacji.
- Monitorowanie kontenera pod kątem scenariuszy ograniczania przepustowości. Jeśli kontener jest coraz intensywnie ograniczany, oznacza to, że ilość danych jest większa niż aprowizowana przepływność, musisz skalować kontener w górę lub zmniejszyć ilość danych (może utworzyć mniejsze partie danych naraz).
- Prawidłowo używasz wzorca do przetwarzania
async/await
wszystkich współbieżnych zadań i nie blokujesz żadnej operacji asynchronicznych.
Przechwytywanie danych diagnostycznych
Wszystkie odpowiedzi w zestawie SDK, w tym CosmosException
, mają Diagnostics
właściwość . Ta właściwość rejestruje wszystkie informacje związane z pojedynczym żądaniem, w tym w przypadku ponownych prób lub błędów przejściowych.
Diagnostyka jest zwracana jako ciąg. Ciąg zmienia się wraz z każdą wersją, ponieważ został ulepszony w celu rozwiązywania problemów z różnymi scenariuszami. W przypadku każdej wersji zestawu SDK ciąg będzie miał zmiany powodujące niezgodność w formatowaniu. Nie analizujej ciągu, aby uniknąć zmian powodujących niezgodność. Poniższy przykładowy kod pokazuje, jak odczytywać dzienniki diagnostyczne przy użyciu zestawu SDK platformy .NET:
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()
}
Diagnostyka w wersji 3.19 lub nowszej
Struktura JSON ma zmiany powodujące niezgodność z każdą wersją zestawu SDK. To sprawia, że niebezpieczne jest analizowanie. Kod JSON reprezentuje strukturę drzewa żądania przechodzącą przez zestaw SDK. W poniższych sekcjach omówiono kilka kluczowych kwestii, na które należy zwrócić uwagę.
Historia procesora CPU
Wysokie wykorzystanie procesora CPU jest najczęstszą przyczyną wolnych żądań. Aby uzyskać optymalne opóźnienie, użycie procesora powinno wynosić około 40%. Użyj interwału 10 sekund, aby monitorować maksymalne (a nie średnie) użycie procesora. Skoki użycia procesora CPU są bardziej typowe w przypadku zapytań obejmujących wiele partycji, w których żądania mogą wykonywać wiele połączeń dla pojedynczego zapytania.
Limity czasu obejmują diagnostykę, która zawiera następujące elementy, na przykład:
"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
Jeśli wartości są powyżej 70 procent, limit czasu może być spowodowany wyczerpaniem procesora CPU. W takim przypadku rozwiązaniem jest zbadanie źródła dużego użycia procesora CPU i zmniejszenie go lub przeskalowanie maszyny do większego rozmiaru zasobów.threadInfo/isThreadStarving
Jeśli węzły mająTrue
wartości, przyczyną jest głód wątku. W takim przypadku rozwiązaniem jest zbadanie źródła lub źródeł głodu wątku (potencjalnie zablokowanych wątków) lub skalowanie maszyny lub maszyn do większego rozmiaru zasobu.dateUtc
Jeśli czas między pomiarami nie wynosi około 10 sekund, wskazuje również rywalizację o pulę wątków. Procesor CPU jest mierzony jako niezależne zadanie, które jest w kolejce w puli wątków co 10 sekund. Jeśli czas między pomiarami jest dłuższy, oznacza to, że zadania asynchroniczne nie mogą być przetwarzane w sposób terminowy. Najbardziej typowym scenariuszem jest to, że kod aplikacji blokuje wywołania za pośrednictwem kodu asynchronicznego.
Rozwiązanie
Aplikacja kliencka korzystająca z zestawu SDK powinna zostać przeskalowana w górę lub w poziomie.
HttpResponseStats
HttpResponseStats
to żądania, które przechodzą do bramy. Nawet w trybie bezpośrednim zestaw SDK pobiera wszystkie informacje o metadanych z bramy.
Jeśli żądanie jest powolne, najpierw sprawdź, czy żadna z poprzednich sugestii nie daje żądanych wyników. Jeśli nadal działa wolno, różne wzorce wskazują na różne problemy. Poniższa tabela zawiera więcej szczegółów.
Liczba żądań | Scenariusz | Opis |
---|---|---|
Jeden do wszystkich | Limit czasu żądania lub HttpRequestExceptions |
Wskazuje na wyczerpanie portów SNAT lub brak zasobów na maszynie w celu przetworzenia żądania w czasie. |
Pojedynczy lub niewielki procent (umowa SLA nie jest naruszona) | Wszystko | Pojedynczy lub niewielki procent wolnych żądań może być spowodowany kilkoma różnymi przejściowymi problemami i powinien być oczekiwany. |
Wszystko | Wszystko | Wskazuje na problem z infrastrukturą lub siecią. |
Umowa SLA naruszona | Brak zmian w aplikacji i umowa SLA została porzucona. | Wskazuje na problem z usługą 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
reprezentuje pojedyncze żądanie do usługi Azure Cosmos DB przy użyciu trybu bezpośredniego z protokołem TCP.
Jeśli nadal działa wolno, różne wzorce wskazują na różne problemy. Poniższa tabela zawiera więcej szczegółów.
Liczba żądań | Scenariusz | Opis |
---|---|---|
Jeden do wszystkich | StoreResult Zawiera TransportException |
Wskazuje na wyczerpanie portów SNAT lub brak zasobów na maszynie w celu przetworzenia żądania w czasie. |
Pojedynczy lub niewielki procent (umowa SLA nie jest naruszona) | Wszystko | Pojedynczy lub niewielki procent wolnych żądań może być spowodowany kilkoma różnymi przejściowymi problemami i powinien być oczekiwany. |
Wszystko | Wszystko | Problem z infrastrukturą lub siecią. |
Umowa SLA naruszona | Żądania zawierają wiele kodów błędów błędów, takich jak 410 |
Wskazuje na problem z usługą Azure Cosmos DB lub maszyną kliencką. |
Umowa SLA naruszona | StorePhysicalAddress są takie same, bez kodu stanu błędu. |
Prawdopodobnie występuje problem z usługą Azure Cosmos DB. |
Umowa SLA naruszona | StorePhysicalAddress mają ten sam identyfikator partycji, ale różne identyfikatory replik bez kodu stanu błędu. |
Prawdopodobnie występuje problem z usługą Azure Cosmos DB. |
Umowa SLA naruszona | StorePhysicalAddress jest losowy, bez kodu stanu błędu. |
Wskazuje na problem z maszyną. |
W przypadku wielu wyników magazynu dla pojedynczego żądania należy pamiętać o następujących kwestiach:
- Silna spójność i powiązana spójność nieaktualności zawsze mają co najmniej dwa wyniki magazynu.
- Sprawdź kod stanu każdego
StoreResult
elementu . Zestaw SDK ponawia próbę automatycznie na wielu różnych błędach przejściowych. Zestaw SDK jest stale ulepszany w celu pokrycia większej liczby scenariuszy.
RequestTimeline
Pokaż czas na różne etapy wysyłania i odbierania żądania w warstwie transportu.
ChannelAcquisitionStarted
: czas na pobranie lub utworzenie nowego połączenia. Połączenia można utworzyć z wielu powodów, takich jak: Poprzednie połączenie zostało zamknięte z powodu braku aktywności przy użyciu elementu CosmosClientOptions.IdleTcpConnectionTimeout, liczba współbieżnych żądań przekracza wartość CosmosClientOptions.MaxRequestsPerTcpConnection, połączenie zostało zamknięte z powodu błędu sieciowego lub aplikacja nie jest stale tworzona zgodnie ze wzorcem singleton , a nowe wystąpienia są stale tworzone. Po nawiązaniu połączenia jest ono ponownie używane dla kolejnych żądań, więc nie powinno to mieć wpływu na opóźnienie P99, chyba że występują wcześniej wymienione problemy.Pipelined
czas jest duży, może być spowodowany dużym żądaniem.Transit time
jest duży, co prowadzi do problemu z siecią. Porównaj tę liczbę z .BELatencyInMs
JeśliBELatencyInMs
jest mała, to czas spędzony w sieci, a nie w usłudze Azure Cosmos DB.Received
czas jest duży może być spowodowany problemem z głodem wątku. Jest to czas między otrzymaniem odpowiedzi a zwróceniem wyniku.
ServiceEndpointStatistics
Informacje o określonym serwerze zaplecza. Zestaw SDK może otwierać wiele połączeń z jednym serwerem zaplecza w zależności od liczby oczekujących żądań i maxConcurrentRequestsPerConnection.
inflightRequests
Liczba oczekujących żądań na serwer zaplecza (może z różnych partycji). Duża liczba może prowadzić do większego ruchu i większych opóźnień.openConnections
to łączna liczba połączeń otwartych dla pojedynczego serwera zaplecza. Może to być przydatne, aby pokazać wyczerpanie portów SNAT, jeśli ta liczba jest bardzo wysoka.
Statystyki połączeń
Informacje o konkretnym połączeniu (nowym lub starym), do którego zostanie przypisane żądanie.
waitforConnectionInit
: Bieżące żądanie czekało na ukończenie nowej inicjowania połączenia. Doprowadzi to do wyższych opóźnień.callsPendingReceive
: liczba wywołań oczekujących na odebranie przed wysłaniem tego połączenia. Duża liczba może pokazać nam, że było wiele połączeń przed tym wywołaniem i może to prowadzić do wyższych opóźnień. Jeśli ta liczba jest duża, wskazuje na problem z blokowaniem wiersza prawdopodobnie spowodowany przez inne żądanie, takie jak zapytanie lub operacja kanału informacyjnego, która trwa długo. Spróbuj zmniejszyć liczbę kanałów CosmosClientOptions.MaxRequestsPerTcpConnection.LastSentTime
: Czas ostatniego żądania wysłanego na ten serwer. Może to być używane wraz z lastReceivedTime w celu wyświetlenia problemów z łącznością lub punktem końcowym. Jeśli na przykład istnieje wiele limitów czasu odbierania, czas wysyłania będzie znacznie większy niż czas odbierania.lastReceive
: Czas ostatniego żądania odebranego z tego serweralastSendAttempt
: Godzina ostatniej próby wysłania
Rozmiary żądań i odpowiedzi
requestSizeInBytes
: całkowity rozmiar żądania wysłanego do usługi Azure Cosmos DBresponseMetadataSizeInBytes
: rozmiar nagłówków zwracanych z usługi Azure Cosmos DBresponseBodySizeInBytes
: rozmiar zawartości zwróconej z usługi 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
}
Współczynnik niepowodzeń narusza umowę SLA usługi Azure Cosmos DB
Skontaktuj się z pomoc techniczna platformy Azure.
Następne kroki
- Diagnozowanie i rozwiązywanie problemów podczas korzystania z zestawu .NET SDK usługi Azure Cosmos DB.
- Dowiedz się więcej o wytycznych dotyczących wydajności zestawu .NET SDK.
- Dowiedz się więcej o najlepszych rozwiązaniach dotyczących zestawu .NET SDK