Megosztás:


Lassú kérelmek diagnosztizálása és hibaelhárítása az Azure Cosmos DB .NET SDK-ban

Az Azure Cosmos DB-ben lassú kéréseket tapasztalhat. A késések több okból is előfordulhatnak, például a kérelmek szabályozása vagy az alkalmazás kialakításának módja. Ez a cikk a probléma különböző kiváltó okait ismerteti.

Túl magas kérelemmennyiség

A lekérdezések korlátozása a lassú lekérdezések leggyakoribb oka. Az Azure Cosmos DB korlátozza a kéréseket, ha túllépik az adatbázis vagy tároló számára kiosztott Request Unit (RU) egységeket. Az SDK beépített logikával rendelkezik a kérések újrapróbálkozásához. A túl nagy kérési arány hibaelhárító cikk bemutatja, hogyan ellenőrizheti, hogy a kérések visszafogása folyamatban van-e. A cikk azt is ismerteti, hogyan méretezheti a fiókját, hogy a jövőben elkerülhesse ezeket a problémákat.

Az alkalmazás kialakítása

Az alkalmazás tervezésekor kövesse a .NET SDK ajánlott eljárásait a legjobb teljesítmény érdekében. Ha az alkalmazás nem követi az SDK ajánlott eljárásait, lassú vagy sikertelen kérelmeket kaphat.

Az alkalmazás fejlesztésekor vegye figyelembe a következőket:

Metaadat-műveletek

Ha ellenőriznie kell, hogy létezik-e egy adatbázis vagy tároló, ne hívja meg a Create...IfNotExistsAsync vagy Read...Async, mielőtt bármilyen tételműveletet hajtana végre. Az ellenőrzést csak akkor kell elvégezni az alkalmazás indításakor, ha szükséges, ha azt szeretné, hogy töröljék őket. Ezek a metaadat-műveletek további késést okoznak, nem rendelkeznek szolgáltatásiszint-szerződéssel (SLA), és külön korlátozásokkal rendelkeznek. Nem skálázhatók adatműveletként.

Lassú igénylések csoportos módban

A tömeges mód egy átviteli sebességre optimalizált mód, amely nagy adatmennyiség-műveletekhez készült, nem késésoptimalizált mód; a rendelkezésre álló átviteli sebesség telítésére szolgál. Ha lassú kéréseket tapasztal tömeges mód használatakor, győződjön meg arról, hogy:

  • Az alkalmazás kiadási konfigurációban van lefordítva.
  • Nem méri a késést az alkalmazás hibakeresése közben (nincs hibakereső csatlakoztatva).
  • A műveletek mennyisége magas, 1000-nél kevesebb művelethez ne használjon tömegesen. A kiosztott átviteli sebesség határozza meg, hogy másodpercenként hány műveletet lehet feldolgozni; a tömeges feldolgozás során a cél az lenne, hogy ebből minél többet kihasználjunk.
  • Kövesse nyomon a tárolót teljesítménykorlátozási forgatókönyvek esetén. Ha a tároló jelentősen szabályozva van, az azt jelenti, hogy az adatok mennyisége nagyobb, mint a kiosztott átviteli sebesség, fel kell skáláznia a tárolót, vagy csökkentenie kell az adatmennyiséget (esetleg egyszerre kisebb adatkötegeket kell létrehoznia).
  • Helyesen használja a mintát az async/await összes egyidejű feladat feldolgozásához, és nem blokkolja az aszinkron műveleteket.

A diagnosztikai adatok rögzítése

Az SDK összes válasza, beleértve CosmosException, rendelkezik egy Diagnostics tulajdonsággal. Ez a tulajdonság az egyetlen kéréssel kapcsolatos összes információt rögzíti, beleértve az újrapróbálkozások vagy átmeneti hibák esetén is.

A diagnosztika karakterláncként kerül visszaadásra. A karakterlánc minden verzióval változik, mivel így javítják a különböző forgatókönyvek hibaelhárításának hatékonyságát. Az SDK minden egyes verziójában a karakterlánc formázásának kompatibilitástörő változásai lesznek. Ne elemezd a karakterláncot, elkerülendő a kompatibilitástörő módosításokat. Az alábbi kódminta bemutatja, hogyan olvashatók be a diagnosztikai naplók a .NET SDK használatával:

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()
}

Diagnosztika a 3.19-es és újabb verzióban

A JSON-struktúra kompatibilitástörő változásokat eredményez az SDK minden verziójában. Így nem biztonságos elemezni. A JSON az SDK-on áthaladó kérés faszerkezetét jelöli. A következő szakaszok néhány fontos szempontot mutatnak be.

Processzorelőzmények

A lassú kérelmek leggyakoribb oka a magas CPU-kihasználtság. Az optimális késéshez a processzorkihasználtságnak nagyjából 40 százalékosnak kell lennie. A maximális (nem átlagos) processzorkihasználtságot 10 másodperces időközönként monitorozza. A cpu-csúcsok gyakoribbak a partíciók közötti lekérdezésekben, ahol a kérések több kapcsolatot is létesíthetnek egyetlen lekérdezéshez.

Az időtúllépések diagnosztikát is magukban foglalnak, amelyek például a következőket tartalmazzák:

"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",
....
}

},
...
]
  • Ha az cpu értékek 70 százalék felett vannak, az időtúllépést valószínűleg a processzorkimerülés okozza. Ebben az esetben a megoldás a magas CPU-kihasználtság forrásának vizsgálata és a kihasználtság csökkentése, vagy a gép felskálázása egy nagyobb erőforrás-méretre.
  • Ha a threadInfo/isThreadStarving csomópontok True értékekkel rendelkeznek, az ok a szálak éhezése lehet. Ebben az esetben a megoldás az, hogy megvizsgáljuk a száléhezés (esetlegesen zárolt szálak) forrását vagy forrásait, vagy a gépet vagy gépeket nagyobb erőforrásokra méretezzük át.
  • Ha a dateUtc mérések közötti idő nem körülbelül 10 másodperc, az a szálkészleten fennálló versengést is jelzi. A CPU mint független feladat van mérve, amely 10 másodpercenként van sorba állítva a szálmedencében. Ha a mérések közötti idő hosszabb, az azt jelzi, hogy az aszinkron feladatok nem dolgozhatók fel időben. A leggyakoribb forgatókönyv az, amikor az alkalmazáskód blokkolja az aszinkron kódon keresztüli hívásokat.

Solution

Az SDK-t használó ügyfélalkalmazást horizontálisan vagy vertikálisan fel kell skálázni.

HttpResponseStats

HttpResponseStatsaz átjáróra irányuló kérések. Az SDK még közvetlen módban is lekéri az átjáró összes metaadat-információját.

Ha a kérés lassú, először ellenőrizze, hogy az előző javaslatok egyike sem adja-e meg a kívánt eredményt. Ha még mindig lassú, a különböző minták különböző problémákra mutatnak. Az alábbi táblázat további részleteket tartalmaz.

Kérelmek száma Scenario Description
Egy mindenkihez Kérelem időtúllépés vagy HttpRequestExceptions Az SNAT-portok kimerültségére vagy a kérés időben történő feldolgozásához szükséges erőforrások hiányára mutat.
Egy vagy kis százalék (az SLA nem sérül) All A lassú kérések egy vagy kis százalékát számos különböző átmeneti probléma okozhatja, és várható.
All All Az infrastruktúrával vagy hálózatkezeléssel kapcsolatos problémára mutat.
SLA megsértve Az alkalmazás nem változott, és az SLA csökkent. Az Azure Cosmos DB szolgáltatással kapcsolatos problémára mutat.
"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 egyetlen kérést jelöl az Azure Cosmos DB-nek a TCP protokollal való közvetlen mód használatával.

Ha még mindig lassú, a különböző minták különböző problémákra mutatnak. Az alábbi táblázat további részleteket tartalmaz.

Kérelmek száma Scenario Description
Egy mindenkihez StoreResult tartalmaz TransportException Az SNAT-portok kimerültségére vagy a kérés időben történő feldolgozásához szükséges erőforrások hiányára mutat.
Egy vagy kis százalék (az SLA nem sérül) All A lassú kérések egy vagy kis százalékát számos különböző átmeneti probléma okozhatja, és várható.
All All Az infrastruktúrával vagy a hálózatkezeléssel kapcsolatos probléma.
SLA megsértve A kérelmek több hibakódot is tartalmaznak, például 410 Az Azure Cosmos DB szolgáltatással vagy az ügyfélszámítógéppel kapcsolatos problémára mutat.
SLA megsértve StorePhysicalAddress ugyanaz, hibaállapotkód nélkül. Valószínűleg az Azure Cosmos DB-vel kapcsolatos probléma.
SLA megsértve StorePhysicalAddress ugyanazzal a partícióazonosítóval, de különböző replikaazonosítókkal rendelkezik, hibaállapotkód nélkül. Valószínűleg az Azure Cosmos DB-vel kapcsolatos probléma.
SLA megsértve StorePhysicalAddress véletlenszerű, hibaállapotkód nélkül. A géppel kapcsolatos problémára mutat.

Egyetlen kérelem több áruházbeli találata esetén vegye figyelembe az alábbiakat:

  • Az erős konzisztencia és a korlátozott elavulási konzisztencia mindig legalább két tárolási műveletek eredményeivel rendelkezik.
  • Ellenőrizze az egyes StoreResult elemek állapotkódját. Az SDK automatikusan újrapróbálkozott több különböző átmeneti hiba esetén. Az SDK folyamatosan fejlesztve van, hogy több forgatókönyvet is lefedjen.

Kérelem-idővonal

A kérések szállítási rétegben való elküldésének és fogadásának különböző szakaszaihoz tartozó idő megjelenítése.

  • ChannelAcquisitionStarted: Az új kapcsolat beszerzésének vagy létrehozásának ideje. A kapcsolatok számos okból hozhatók létre, például: Az előző kapcsolatot a CosmosClientOptions.IdleTcpConnectionTimeout inaktivitása miatt zárták le, az egyidejű kérések mennyisége meghaladja a CosmosClientOptions.MaxRequestsPerTcpConnection értéket, a kapcsolat hálózati hiba miatt lett lezárva, vagy az alkalmazás nem követi a Singleton-mintát, és folyamatosan új példányok jönnek létre. Miután létrejött egy kapcsolat, a rendszer újra felhasználja a későbbi kérésekhez, így ez nem befolyásolhatja a P99 késését, kivéve, ha a korábban említett problémák történnek.
  • Pipelined: A kérelem TCP-szoftvercsatornába való írásával töltött idő. A kérések egyszerre csak TCP-szoftvercsatornára írhatók, a nagy érték pedig szűk keresztmetszetet jelez a TCP-szoftvercsatornán, amelyet az alkalmazáskód vagy a nagy kérések mérete általában zárolt szálakhoz társít.
  • Transit time: A hálózaton töltött idő, miután a kérést a TCP-szoftvercsatornára írták. Hasonlítsa össze ezt a számot a BELatencyInMs. Ha BELatencyInMs kicsi, akkor az időt a hálózaton, és nem az Azure Cosmos DB szolgáltatásban töltötték. Ha a kérés időtúllépéssel meghiúsult, az azt jelzi, hogy az ügyfél mennyi ideig várt válasz nélkül, és a forrás hálózati késés.
  • Received: A válasz beérkezése és feldolgozása közötti idő az SDK által. A nagy értéket általában egy szál éhezése vagy zárolt szálak okozzák.

SzolgáltatásVégpontStatisztikák

Információk egy adott háttérkiszolgálóról. Az SDK több kapcsolatot is megnyithat egyetlen háttérkiszolgálón a függőben lévő kérelmek számától és a MaxConcurrentRequestsPerConnectiontól függően.

  • inflightRequests A háttérkiszolgálóra irányuló függőben lévő kérések száma (esetleg különböző partíciókról). A magas szám nagyobb forgalmat és nagyobb késést eredményezhet.
  • openConnections az egyetlen háttérkiszolgáló felé megnyitott kapcsolatok teljes száma. Ez hasznos lehet az SNAT-portok kimerülésének megjelenítéséhez, ha ez a szám nagyon magas.

ConnectionStatistics

Az adott kapcsolatra (új vagy régi) vonatkozó információk, amelyhez a kérés hozzá van rendelve.

  • waitforConnectionInit: Az aktuális kérés az új kapcsolat inicializálásának befejezésére várt. Ez magasabb késésekhez vezet.
  • callsPendingReceive: A hívás elküldése előtt függőben lévő hívások száma. A magas szám azt mutathatja, hogy sok hívás volt a hívás előtt, és ez magasabb késésekhez vezethet. Ha ez a szám magas, az egy sorblokkolási problémára mutat, amelyet esetleg egy másik kérés, például egy lekérdezési vagy hírcsatorna-művelet okoz, amely hosszú ideig tart a feldolgozáshoz. Próbálja meg csökkenteni a CosmosClientOptions.MaxRequestsPerTcpConnection értéket a csatornák számának növeléséhez.
  • LastSentTime: A kiszolgálónak küldött utolsó kérés időpontja. Ez a LastReceivedTime-tal együtt a kapcsolati vagy végponti problémák megtekintésére is használható. Ha például sok a fogadási időtúllépés, az elküldött idő sokkal nagyobb lesz, mint a fogadási idő.
  • lastReceive: A kiszolgálótól kapott utolsó kérés időpontja
  • lastSendAttempt: Az utolsó küldési kísérlet időpontja

Kérelem- és válaszméretek

  • requestSizeInBytes: Az Azure Cosmos DB-nek küldött kérelem teljes mérete
  • responseMetadataSizeInBytes: Az Azure Cosmos DB-ből visszaadott fejlécek mérete
  • responseBodySizeInBytes: Az Azure Cosmos DB-ből visszaadott tartalom mérete
"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
}

A hibaarány sérti az Azure Cosmos DB SLA-t

Lépjen kapcsolatba Azure-támogatás.

Következő lépések