Diagnose und Fehlerbehebung bei langsamen Anforderungen in Azure Cosmos DB .NET SDK
GILT FÜR: NoSQL
In Azure Cosmos DB bemerken Sie möglicherweise langsame Anforderungen. Verzögerungen können aus verschiedenen Gründen auftreten, z. B. durch die Drosselung von Anforderungen oder die Art und Weise, wie Ihre Anwendung konzipiert ist. Dieser Artikel erklärt die verschiedenen Ursachen für dieses Problem.
Anforderungsrate zu groß
Die Einschränkung von Anforderungen ist der häufigste Grund für langsame Anforderungen. Azure Cosmos DB drosselt Anforderungen, wenn sie die zugewiesenen Anforderungseinheiten für die Datenbank oder den Container überschreiten. Das SDK verfügt über eine integrierte Logik zur Wiederholung dieser Anforderungen. Der Artikel zur Problembehandlung bei zu hoher Anforderungsrate erklärt, wie Sie überprüfen können, ob die Anforderungen gedrosselt werden. In diesem Artikel wird auch erläutert, wie Sie Ihr Konto skalieren, um diese Probleme in Zukunft zu vermeiden.
Anwendungsentwurf
Wenn Sie Ihre Anwendung entwerfen, befolgen Sie die bewährten Methoden für das .NET SDK, um die beste Leistung zu erzielen. Wenn Ihre Anwendung die SDK Best Practices nicht befolgt, kann es zu langsamen oder fehlgeschlagenen Anforderungen kommen.
Beachten Sie bei der Entwicklung Ihrer Anwendung die folgenden Punkte:
- Die Anwendung sollte sich in der gleichen Region befinden wie Ihr Azure Cosmos DB-Konto.
- Ihre Parameter ApplicationRegion oder ApplicationPreferredRegions sollten Ihre regionalen Präferenzen widerspiegeln und auf die Region verweisen, in der Ihre Anwendung bereitgestellt wird.
- Durch hohen Datenverkehr kann es zu einem Engpass in der Netzwerkschnittstelle kommen. Wenn die Anwendung auf virtuellen Azure-Computern ausgeführt wird, gibt es mögliche Problemumgehungen:
- Erwägen Sie die Erstellung eines virtuellen Computers, auf dem der beschleunigte Netzwerkbetrieb aktiviert ist.
- Aktivieren Sie den beschleunigten Netzwerkbetrieb auf einem vorhandenen virtuellen Computer.
- Verwenden Sie ggf. einen leistungsfähigeren virtuellen Computer.
- Bevorzugen Sie den direkten Konnektivitätsmodus.
- Vermeiden Sie eine hohe CPU-Auslastung. Achten Sie darauf, dass Sie die maximale CPU betrachten und nicht den Durchschnitt, der bei den meisten Protokollierungssystemen voreingestellt ist. Alles, was über etwa 40 Prozent liegt, kann die Latenz erhöhen.
Metadatenvorgänge
Wenn Sie überprüfen müssen, ob eine Datenbank oder ein Container vorhanden ist, rufen Sie Create...IfNotExistsAsync
oder Read...Async
nicht auf, bevor Sie einen Elementvorgang durchführen. Die Validierung sollte nur beim Start der Anwendung erfolgen, wenn Sie erwarten, dass sie gelöscht werden. Diese Metadatenvorgänge generieren zusätzliche Latenz, verfügen über keine Vereinbarung zum Servicelevel (SLA) und verfügen über eigene separate Einschränkungen. Sie werden nicht wie Datenvorgänge skaliert.
Langsame Anforderungen im Massenmodus
Der Massenmodus ist ein durchsatzoptimierter Modus, der für Vorgänge mit hohem Datenvolumen und nicht für latenzoptimierte Vorgänge bestimmt ist. Er soll den verfügbaren Durchsatz ausnutzen. Wenn Sie bei der Verwendung des Massenmodus bemerken, dass Anforderungen langsam sind, stellen Sie Folgendes sicher:
- Ihre Anwendung ist in der Releasekonfiguration kompiliert.
- Beim Debuggen der Anwendung wird die Latenz nicht gemessen (es sind keine Debugger angefügt).
- Das Volumen der Vorgänge ist hoch. Verwenden Sie den Massenmodus nicht für weniger als 1.000 Vorgänge. Der bereitgestellte Durchsatz bestimmt, wie viele Vorgänge pro Sekunde verarbeitet werden können. Das Ziel beim Massenmodus ist die höchstmögliche Auslastung.
- Überwachen Sie den Container auf Drosselungsszenarien. Wenn der Container stark gedrosselt wird, bedeutet das, dass die Datenmenge größer als der bereitgestellte Durchsatz ist. Sie müssen den Container entweder hochskalieren oder die Datenmenge reduzieren (vielleicht erstellen Sie jeweils kleinere Datenbatches).
- Sie verwenden das Muster
async/await
ordnungsgemäß, um alle gleichzeitigen Aufgaben zu verarbeiten, und Sie blockieren keine asynchronen Vorgänge.
Capture-Diagnose
Alle Antworten im SDK, einschließlich CosmosException
, haben eine Diagnostics
-Eigenschaft. In dieser Eigenschaft werden alle Informationen zu einer einzelnen Anforderung aufgezeichnet, unter anderem auch, ob es Wiederholungsversuche oder vorübergehende Fehler gab.
Die Diagnosen werden als Zeichenfolge zurückgegeben. Der String ändert sich mit jeder Version, da er für die Fehlersuche in verschiedenen Szenarien verbessert wurde. Mit jeder Version des SDK wird die Formatierung der Zeichenfolge geändert. Analysieren Sie die Zeichenfolge nicht, um Breaking Changes zu vermeiden. Das folgende Codebeispiel zeigt, wie Diagnoseprotokolle mit dem .NET SDK gelesen werden:
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()
}
Diagnostik in Version 3.19 und höher
Die JSON-Struktur hat sich mit jeder Version des SDK geändert. Das macht sie unsicher beim Parsen. Das JSON stellt eine Baumstruktur der Anforderungen dar, die das SDK durchlaufen. In den folgenden Abschnitten werden einige wichtige Punkte behandelt.
CPU-Verlauf
Eine hohe CPU-Auslastung ist die häufigste Ursache für langsame Anforderungen. Für optimale Latenz sollte die CPU-Auslastung ungefähr 40 Prozent betragen. Verwenden Sie 10 Sekunden als Intervall zur Überwachung der maximalen (nicht durchschnittlichen) CPU-Nutzung. CPU-Spitzen treten häufiger bei partitionsübergreifenden Abfragen auf, bei denen die Anforderungen möglicherweise mehrere Konnektivitäten für eine einzige Abfrage erfordern.
Zu den Timeouts gehört die Diagnose, die Folgendes enthält, z. B.:
"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",
....
}
},
...
]
- Wenn die
cpu
-Werte über 70 Prozent liegen, ist die Zeitüberschreitung wahrscheinlich auf eine Erschöpfung der CPU zurückzuführen. In diesem Fall besteht die Lösung darin, die Quelle für die hohe CPU-Auslastung zu ermitteln und für eine Reduzierung zu sorgen oder die Ressourcengröße für den Computer zu erhöhen. - Wenn die
threadInfo/isThreadStarving
-KnotenTrue
-Werte enthalten, ist die Ursache Threadmangel. In diesem Fall besteht die Lösung darin, die Quelle(n) des Threadmangels (möglicherweise gesperrte Threads) zu untersuchen oder den oder die Rechner auf eine größere Ressourcengröße zu skalieren. - Wenn die
dateUtc
-Zeit zwischen den Messungen nicht etwa 10 Sekunden beträgt, deutet dies ebenfalls auf eine Konkurrenzsituation im Thread-Pool hin. Die CPU wird als eine unabhängige Aufgabe gemessen, die alle 10 Sekunden in den Thread-Pool eingereiht wird. Wenn die Zeit zwischen den Messungen länger ist, gibt dies an, dass die asynchronen Aufgaben nicht rechtzeitig verarbeitet werden können. Das häufigste Szenario ist, dass Ihr Anwendungscode Aufrufe über asynchronen Code blockiert.
Lösung
Die Clientanwendung, die das SDK verwendet, sollte entsprechend skaliert werden.
HttpResponseStats
HttpResponseStats
sind Anforderungen, die an das Gateway gerichtet werden. Selbst im direkten Modus erhält das SDK alle Metadaten vom Gateway.
Wenn die Anforderung langsam ist, überprüfen Sie zunächst, ob keiner der vorherigen Vorschläge die gewünschten Ergebnisse liefert. Wenn es immer noch langsam ist, deuten verschiedene Muster auf verschiedene Probleme hin. Die folgende Tabelle enthält weitere Einzelheiten.
Anzahl von Anforderungen | Szenario | BESCHREIBUNG |
---|---|---|
Einzeln bis alle | Anforderungstimeout oder HttpRequestExceptions |
Weist darauf hin, dass der SNAT-Port erschöpft ist oder dass die Ressourcen des Rechners nicht ausreichen, um die Anforderung rechtzeitig zu bearbeiten. |
Einzelner oder kleiner Prozentsatz (SLA wird nicht verletzt) | Alle | Ein einzelner oder kleiner Prozentsatz langsamer Anforderungen kann durch verschiedene vorübergehende Probleme verursacht werden und sollte erwartet werden. |
All | All | Weist auf ein Problem mit der Infrastruktur oder dem Netzwerk hin. |
SLA-Verletzung | Keine Änderungen an der Anwendung und SLA verworfen | Weist auf ein Problem mit dem Azure Cosmos DB-Dienst hin. |
"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
stellt eine einzelne Anforderung an Azure Cosmos DB dar, indem der direkte Modus mit dem TCP-Protokoll verwendet wird.
Wenn es immer noch langsam ist, deuten verschiedene Muster auf verschiedene Probleme hin. Die folgende Tabelle enthält weitere Einzelheiten.
Anzahl von Anforderungen | Szenario | BESCHREIBUNG |
---|---|---|
Einzeln bis alle | StoreResult enthält TransportException |
Weist darauf hin, dass der SNAT-Port erschöpft ist oder dass die Ressourcen des Rechners nicht ausreichen, um die Anforderung rechtzeitig zu bearbeiten. |
Einzelner oder kleiner Prozentsatz (SLA wird nicht verletzt) | Alle | Ein einzelner oder kleiner Prozentsatz langsamer Anforderungen kann durch verschiedene vorübergehende Probleme verursacht werden und sollte erwartet werden. |
All | Alle | Ein Problem mit der Infrastruktur oder dem Netzwerk. |
SLA-Verletzung | Anforderungen enthalten mehrere Fehlercodes, wie 410 . |
Verweist auf ein Problem mit dem Azure Cosmos DB-Dienst oder dem Clientcomputer. |
SLA-Verletzung | StorePhysicalAddress sind identisch, ohne Fehlerstatuscode. |
Wahrscheinlich ein Problem mit Azure Cosmos DB. |
SLA-Verletzung | StorePhysicalAddress haben dieselbe Partitions-ID, aber unterschiedliche Replikations-IDs, ohne dass ein Fehlerstatuscode vorliegt. |
Wahrscheinlich ein Problem mit Azure Cosmos DB. |
SLA-Verletzung | StorePhysicalAddress ist zufällig und hat keinen Fehlerstatuscode. |
Verweist auf ein Problem mit dem Computer. |
Beachten Sie bei mehreren Speicherergebnissen für eine einzelne Anforderung Folgendes:
- Starke Konsistenz und begrenzte Staleness-Konsistenz haben immer mindestens zwei Speicherergebnisse.
- Prüfen Sie den Statuscode jedes
StoreResult
. Das SDK führt bei mehreren verschiedenen vorübergehenden Fehlschlägen automatisch Wiederholungsversuche durch. Das SDK wird ständig verbessert, um mehr Szenarien abzudecken.
RequestTimeline
Zeigt die Zeit für die verschiedenen Phasen des Sendens und Empfangens einer Anforderung in der Datentransportebene an.
ChannelAcquisitionStarted
: Die Zeit, um eine neue Verbindung zu erhalten oder herzustellen. Verbindungen können aus zahlreichen Gründen erstellt werden, z. B.: Die vorherige Verbindung wurde aufgrund von Inaktivität mit CosmosClientOptions.IdleTcpConnectionTimeout geschlossen, das Volumen gleichzeitiger Anforderungen überschreitet die CosmosClientOptions.MaxRequestsPerTcpConnection, die Verbindung wurde aufgrund eines Netzwerkfehlers geschlossen, oder die Anwendung folgt nicht dem Singleton-Muster , und es werden ständig neue Instanzen erstellt. Sobald eine Verbindung hergestellt wurde, wird sie für nachfolgende Anforderungen wiederverwendet, sodass sich dies nicht auf die P99-Latenz auswirken sollte, es sei denn, die zuvor erwähnten Probleme treten auf.Pipelined
: Die Zeit, die für das Schreiben der Anforderung in den TCP-Socket benötigt wird Anforderungen können immer nur einzeln an einen TCP-Socket geschrieben werden. Ein großer Wert deutet auf einen Engpass auf dem TCP-Socket in der Regel in Verbindung mit gesperrten Threads durch den Anwendungscode oder große Anforderungen hin.Transit time
: Die Zeit, die für das Netzwerk aufgewendet wurde, nachdem die Anforderung auf den TCP-Socket geschrieben wurde Vergleichen Sie diese Zahl mit derBELatencyInMs
. WennBELatencyInMs
gering ist, wurde die Zeit im Netzwerk verbracht und nicht mit dem Azure Cosmos DB-Dienst. Wenn die Anforderung mit einem Timeout fehlgeschlagen ist, zeigt dies an, wie lange der Client erfolglos auf eine Antwort gewartet hat, und die Quelle ist die Netzwerklatenz.Received
: Der Zeitraum zwischen dem Empfang der Antwort und der Verarbeitung durch das SDK Ein großer Wert wird in der Regel durch Thread-Starvation oder gesperrte Threads verursacht.
ServiceEndpointStatistics
Informationen zu einem bestimmten Back-End-Server. Das SDK kann mehrere Verbindungen zu einem einzelnen Back-End-Server öffnen, abhängig von der Anzahl der ausstehenden Anforderungen und dem Parameter MaxConcurrentRequestsPerConnection.
inflightRequests
Die Anzahl der ausstehenden Anforderungen an einen Back-End-Server (möglicherweise aus verschiedenen Partitionen). Eine hohe Anzahl kann zu mehr Datenverkehr und höheren Latenzen führen.openConnections
ist die Gesamtanzahl der Verbindungen, die für einen einzelnen Back-End-Server geöffnet sind. Dies kann nützlich sein, um die Erschöpfung des SNAT-Ports anzuzeigen, wenn diese Zahl sehr hoch ist.
ConnectionStatistics
Informationen zu der bestimmten Verbindung (neu oder alt) der Anforderung wird zugewiesen.
waitforConnectionInit
: Die aktuelle Anforderung wartet auf die Initialisierung neuer Verbindungen. Dies führt zu längeren Wartezeiten.callsPendingReceive
: Anzahl der Aufrufe, deren Empfang ausstand, bevor dieser Aufruf gesendet wurde. Eine hohe Anzahl kann darauf hinweisen, dass vor diesem Aufruf viele Aufrufe erfolgt sind und dass es zu längeren Wartezeiten kommen kann. Wenn diese Anzahl hoch ist, deutet dies auf ein Head-of-Line-Blockierproblem hin, das möglicherweise durch eine andere Anforderung wie eine Abfrage oder einen Einspeisevorgang verursacht wird, deren Bearbeitung viel Zeit in Anspruch nimmt. Versuchen Sie, die CosmosClientOptions.MaxRequestsPerTcpConnection zu verringern, um die Anzahl der Kanäle zu erhöhen.LastSentTime
: Zeitpunkt der letzten Anforderung, die an diesen Server gesendet wurde. Dies zusammen mit LastReceivedTime kann verwendet werden, um Verbindungs- oder Endpunktprobleme zu erkennen. Wenn es beispielsweise viele Empfangstimeouts gibt, dauert das Senden viel länger als das Empfangen.lastReceive
: Zeitpunkt der letzten Anforderung, die von diesem Server empfangen wurdelastSendAttempt
: Zeitpunkt des letzten Sendeversuchs
Größen von Anforderung und Antwort
requestSizeInBytes
: Die Gesamtgröße der an Azure Cosmos DB gesendeten AnforderungresponseMetadataSizeInBytes
: Die Größe der von Azure Cosmos DB zurückgegebenen HeaderresponseBodySizeInBytes
: Die Größe des von Azure Cosmos DB zurückgegebenen Inhalts
"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
}
Fehlerrate verstößt gegen die Azure Cosmos DB SLA
Kontaktieren Sie den Azure-Support.
Nächste Schritte
- Diagnostizieren und beheben Sie Probleme, wenn Sie das Azure Cosmos DB .NET SDK verwenden.
- Weitere Informationen zu Leistungsrichtlinien für das .NET SDK.
- Weitere Informationen zu den bewährten Methoden für das .NET SDK