Az Azure Cosmos DB és a .NET teljesítményével kapcsolatos tippek

A KÖVETKEZŐRE VONATKOZIK: NoSQL

Az Azure Cosmos DB egy gyors, rugalmas elosztott adatbázis, amely zökkenőmentesen skálázható, garantált késéssel és átviteli sebességgel. Nem kell jelentős architektúramódosításokat végeznie, és nem kell összetett kódot írnia az adatbázis Azure Cosmos DB-vel való skálázásához. A vertikális fel- és leskálázás ugyanolyan egyszerű, mint egyetlen API-hívás. További információkért tekintse meg a tároló átviteli sebességének kiépítését vagy az adatbázis átviteli sebességének kiépítését.

Mivel az Azure Cosmos DB hálózati hívásokon keresztül érhető el, az SQL .NET SDK használatakor ügyféloldali optimalizálásokat végezhet a csúcsteljesítmény elérése érdekében.

Ha javítani szeretné az adatbázis teljesítményét, vegye figyelembe az alábbi szakaszokban ismertetett lehetőségeket.

Üzemeltetési javaslatok

A kiszolgálóoldali szemétgyűjtés bekapcsolása

A szemétgyűjtés gyakoriságának csökkentése bizonyos esetekben segíthet. A .NET-ben állítsa a gcServert a következőretrue: .

Az ügyfél számítási feladatainak vertikális felskálázása

Ha magas átviteli sebességgel vagy másodpercenként 50 000-nél nagyobb kérelemegységnél (RU/s) tesztel, az ügyfélalkalmazás számítási feladatok szűk keresztmetszetévé válhat. Ennek az az oka, hogy a gép túllépheti a processzor- vagy hálózatkihasználtságot. Ha eléri ezt a pontot, folytathatja az Azure Cosmos DB-fiók további leküldését az ügyfélalkalmazások több kiszolgálón való skálázásával.

Feljegyzés

A magas processzorhasználat nagyobb késést és időtúllépési kivételeket okozhat.

Metaadat-műveletek

Ne ellenőrizze, hogy létezik-e Create...IfNotExistsAsync adatbázis és/vagy tároló a gyakori elérési úton és/vagy Read...Async az elemművelet végrehajtása előtt. Az ellenőrzést csak akkor kell elvégezni az alkalmazás indításakor, ha szükséges, ha azt várja, hogy töröljék őket (ellenkező esetben nincs rá szükség). Ezek a metaadat-műveletek további végpontok közötti késést okoznak, nem rendelkeznek SLA-val és saját, nem adatműveletekhez hasonló skálázási korlátozásokkal .

Naplózás és nyomkövetés

Egyes környezetekben engedélyezve van a .NET DefaultTraceListener . A DefaultTraceListener teljesítményproblémákat okoz az éles környezetekben, ami magas processzor- és I/O-szűk keresztmetszeteket okoz. Ellenőrizze és győződjön meg arról, hogy a DefaultTraceListener le van tiltva az alkalmazáshoz úgy, hogy eltávolítja azt az éles környezetekben lévő TraceListenersből .

A legújabb (3.23.0-nál nagyobb) SDK-verziók automatikusan eltávolítják, amikor észlelik. A régebbi verziók esetén a következő módszerekkel távolíthatja el:

if (!Debugger.IsAttached)
{
    Type defaultTrace = Type.GetType("Microsoft.Azure.Cosmos.Core.Trace.DefaultTrace,Microsoft.Azure.Cosmos.Direct");
    TraceSource traceSource = (TraceSource)defaultTrace.GetProperty("TraceSource").GetValue(null);
    traceSource.Listeners.Remove("Default");
    // Add your own trace listeners
}

Hálózat

Csatlakozás ion szabályzat: Közvetlen kapcsolati mód használata

A .NET V3 SDK alapértelmezett csatlakozási módja közvetlen TCP protokollal. A kapcsolati módot a példány létrehozásakor konfigurálja a CosmosClient következőben CosmosClientOptions: . A különböző csatlakozási lehetőségekről a kapcsolati módokról szóló cikkből tudhat meg többet.

string connectionString = "<your-account-connection-string>";
CosmosClient client = new CosmosClient(connectionString,
new CosmosClientOptions
{
    ConnectionMode = ConnectionMode.Gateway // ConnectionMode.Direct is the default
});

Rövid élettartamú portok elfogyása

Ha magas kapcsolati hangerőt vagy magas porthasználatot lát a példányokon, először ellenőrizze, hogy az ügyfélpéldányok egytonnák-e. Más szóval az ügyfélpéldányoknak egyedinek kell lenniük az alkalmazás teljes élettartama során.

Amikor a TCP protokollon fut, az ügyfél a hosszú élettartamú kapcsolatok használatával optimalizálja a késést. Ez ellentétben áll a HTTPS protokollal, amely két perc inaktivitás után leállítja a kapcsolatokat.

Olyan helyzetekben, ahol ritkán fér hozzá, és ha az átjáró módú hozzáféréssel összehasonlítva magasabb kapcsolatszámot észlel, a következőket teheti:

  • Konfigurálja a CosmosClientOptions.PortReuseMode tulajdonságotPrivatePortPool (a keretrendszer 4.6.1-s és újabb verzióival, valamint a .NET Core 2.0-s és újabb verzióival). Ez a tulajdonság lehetővé teszi az SDK számára, hogy rövid élettartamú portokból álló kis készletet használjon a különböző Azure Cosmos DB-célvégpontokhoz.
  • Konfigurálja a CosmosClientOptions.IdleTcp Csatlakozás ionTimeout tulajdonságot 10 percnél hosszabb vagy egyenlő értékre. Az ajánlott értékek 20 perctől 24 óráig tartanak.

A teljesítmény érdekében helyezze el az ügyfeleket ugyanabban az Azure-régióban

Ha lehetséges, helyezzen el minden olyan alkalmazást, amely meghívja az Azure Cosmos DB-t ugyanabban a régióban, mint az Azure Cosmos DB-adatbázis. Íme egy hozzávetőleges összehasonlítás: az ugyanabban a régióban lévő Azure Cosmos DB-be irányuló hívások 1 ezredmásodpercben (ms) és 2 ms között fejeződnek be, de az USA nyugati és keleti partja közötti késés több mint 50 ms. Ez a késés kérésenként eltérő lehet attól függően, hogy a kérés milyen útvonalon halad át az ügyfélről az Azure-adatközpont határára.

A lehető legkisebb késést úgy érheti el, ha biztosítja, hogy a hívó alkalmazás ugyanabban az Azure-régióban legyen, mint a kiépített Azure Cosmos DB-végpont. Az elérhető régiók listájáért tekintse meg az Azure-régiókat.

Az ügyfelek rendezése ugyanabban a régióban.

Szálak/tevékenységek számának növelése

Mivel az Azure Cosmos DB-be irányuló hívások a hálózaton keresztül történik, előfordulhat, hogy a kérések egyidejűségének mértékét módosítania kell, hogy az ügyfélalkalmazás minimális időt töltsön a kérések közötti várakozással. Ha például a .NET-feladat párhuzamos kódtárát használja, több száz olyan feladat sorrendjében hozzon létre, amelyek az Azure Cosmos DB-ből olvasnak vagy írnak.

Gyorsított hálózatkezelés engedélyezése a késés és a PROCESSZOR-jitter csökkentése érdekében

A teljesítmény maximalizálása érdekében javasoljuk, hogy kövesse az utasításokat a gyorsított hálózatkezelés engedélyezéséhez a Windowsban (kattintson az utasításokra) vagy a Linux (kattintson az utasításokra) Azure-beli virtuális gépre.

Gyorsított hálózatkezelés nélkül előfordulhat, hogy az Azure-beli virtuális gép és más Azure-erőforrások között áthaladó IO szükségtelenül a virtuális gép és annak hálózati kártyája között található gazdagépen és virtuális kapcsolón keresztül történik. Miután a gazdagép és a virtuális kapcsoló beágyazott a datapathban, nem csak növeli a késést és a kommunikáció csatornán belüli jittert, hanem a processzorciklusokat is ellopja a virtuális gépről. A gyorsított hálózatkezeléssel a virtuális gép közvetlenül a hálózati adapterhez kapcsolódik közvetítők nélkül; a gazdagép és a virtuális kapcsoló által kezelt hálózati házirendek adatait a hálózati adapter hardverei kezelik; a gazdagép és a virtuális kapcsoló megkerülése. A gyorsított hálózatkezelés engedélyezésekor általában alacsonyabb késésre és nagyobb átviteli sebességre, valamint konzisztensebb késésre és csökkentett processzorhasználatra számíthat.

Korlátozások: A gyorsított hálózatkezelést támogatni kell a virtuálisgép-operációs rendszeren, és csak akkor lehet engedélyezni, ha a virtuális gép leállt és felszabadítva van. A virtuális gép nem telepíthető az Azure Resource Managerrel. Az App Service-ben nincs engedélyezve gyorsított hálózat.

További részletekért tekintse meg a Windows és a Linux utasításait.

SDK-használat

A legújabb SDK telepítése

Az Azure Cosmos DB SDK-k folyamatosan fejlődnek a legjobb teljesítmény érdekében. A legújabb SDK meghatározásához és a fejlesztések áttekintéséhez tekintse át az Azure Cosmos DB SDK-t.

Stream API-k használata

A .NET SDK V3 stream API-kat tartalmaz, amelyek szerializálás nélkül fogadják és visszaadják az adatokat.

Azok a középső rétegbeli alkalmazások, amelyek nem közvetlenül az SDK-ból származó válaszokat használnak fel, de más alkalmazásszintekre továbbítják őket, a stream API-k előnyeit élvezhetik. A streamkezelésre vonatkozó példákért tekintse meg az elemkezelési mintákat.

Egyetlen azure Cosmos DB-ügyfél használata az alkalmazás teljes élettartama alatt

Minden CosmosClient példány szálbiztos, és hatékony kapcsolatkezelést és cím-gyorsítótárazást végez, amikor közvetlen módban működik. A hatékony kapcsolatkezelés és az SDK-ügyfél teljesítményének javítása érdekében javasoljuk, hogy az alkalmazás teljes élettartama alatt egyetlen példányt AppDomain használjon minden olyan fiókhoz, amelyet az alkalmazás használ.

A több fiókot kezelő több-bérlős alkalmazások esetében tekintse meg a kapcsolódó ajánlott eljárásokat.

Az Azure Functions használatakor a példányoknak is követniük kell a meglévő irányelveket , és egyetlen példányt kell fenntartaniuk.

A hívások blokkolásának elkerülése

Az Azure Cosmos DB SDK-t úgy kell megtervezni, hogy egyszerre több kérést is feldolgozz. Az aszinkron API-k lehetővé teszik, hogy egy kis szálkészlet több ezer egyidejű kérést kezeljen azáltal, hogy nem várakozik a blokkoló hívásokra. Ahelyett, hogy egy hosszú ideig futó szinkron feladatra várna, a szál egy másik kérésen is működhet.

Az Azure Cosmos DB SDK-t használó alkalmazások gyakori teljesítményproblémája az aszinkron hívások blokkolása. Számos szinkron blokkoló hívás a szálkészlet éhezéséhez és a válaszidő romlásához vezet.

Ne tegye:

  • Az aszinkron végrehajtás letiltása a Task.Wait vagy a Task.Result meghívásával.
  • A Task.Run használatával szinkronizált API-t készíthet aszinkron módon.
  • Zárolások beszerzése a közös kódútvonalakban. Az Azure Cosmos DB .NET SDK akkor a leghatékonyabb, ha a kód párhuzamos futtatására van kiállítva.
  • Hívja meg a Task.Run parancsot , és azonnal várja meg. ASP.NET Core már futtatja az alkalmazáskódot normál szálkészlet-szálakon, így a Task.Run meghívása csak extra szükségtelen szálkészlet-ütemezést eredményez. Még ha az ütemezett kód blokkolna is egy szálat, a Task.Run ezt nem akadályozza meg.
  • Ne használja a ToList() függvényt Container.GetItemLinqQueryable<T>() , amely blokkolja a hívásokat a lekérdezés szinkron kiürítéséhez. A ToFeedIterator() használatával a lekérdezés aszinkron módon üríthető.

Tegye:

  • Az Azure Cosmos DB .NET API-k aszinkron meghívása.
  • A teljes hívásverem aszinkron, hogy kihasználhassa az aszinkron/várakozási mintákat.

A profilkészítő, például a PerfView segítségével megtalálhatja a szálkészlethez gyakran hozzáadott szálakat. Az Microsoft-Windows-DotNETRuntime/ThreadPoolWorkerThread/Start esemény a szálkészlethez hozzáadott szálat jelzi.

Tartalomválasz letiltása írási műveletekhez

A nagy mennyiségű hasznos adatokkal rendelkező számítási feladatok esetén állítsa a kérési beállítást a EnableContentResponseOnWrite következőre false: . A szolgáltatás többé nem adja vissza a létrehozott vagy frissített erőforrást az SDK-nak. Általában, mivel az alkalmazás rendelkezik a létrehozott objektummal, nem kell a szolgáltatásnak visszaadnia. A fejlécértékek továbbra is elérhetők, például egy kérelemdíj. A tartalomválasz letiltása javíthatja a teljesítményt, mivel az SDK-nak már nincs szüksége memória lefoglalására vagy a válasz törzsének szerializálására. Emellett csökkenti a hálózati sávszélesség használatát, hogy tovább segítse a teljesítményt.

ItemRequestOptions requestOptions = new ItemRequestOptions() { EnableContentResponseOnWrite = false };
ItemResponse<Book> itemResponse = await this.container.CreateItemAsync<Book>(book, new PartitionKey(book.pk), requestOptions);
// Resource will be null
itemResponse.Resource

A tömeges optimalizálás engedélyezése az átviteli sebességre késés helyett

Engedélyezze a Tömeges lehetőséget olyan helyzetekben, ahol a számítási feladat nagy átviteli sebességet igényel, és a késés nem olyan fontos. A Tömeges funkció engedélyezéséről és a használni kívánt forgatókönyvekről további információt a Bevezetés a tömeges támogatásba című témakörben talál.

Gazdagépenkénti System.Net maximális Csatlakozás növelése átjáró mód használatakor

Az Azure Cosmos DB-kérések HTTPS/REST protokollon keresztül lesznek intézve, amikor átjáró módot használ. Gazdanév vagy IP-cím szerint az alapértelmezett kapcsolati korlát vonatkozik rájuk. Előfordulhat, hogy magasabb értéket kell beállítania MaxConnections (100 és 1000 között), hogy az ügyfélkódtár több egyidejű kapcsolatot használjon az Azure Cosmos DB-hez. A .NET SDK 1.8.0-s és újabb verzióiban a ServicePointManager.Default Csatlakozás ionLimit alapértelmezett értéke 50. Az érték módosításához magasabb értéket állíthat be Documents.Client.ConnectionPolicy.MaxConnectionLimit .

Szálak/tevékenységek számának növelése

A cikk Hálózatkezelés szakaszában további információt a szálak/tevékenységek számának növelése című témakörben talál.

Lekérdezési műveletek

A lekérdezési műveletekhez tekintse meg a lekérdezések teljesítményére vonatkozó tippeket.

Indexelési szabályzat

Nem használt útvonalak kizárása az indexelésből a gyorsabb írás érdekében

Az Azure Cosmos DB indexelési szabályzata azt is lehetővé teszi, hogy az indexelési útvonalak (IndexingPolicy.IncludePaths és IndexingPolicy.ExcludedPaths) használatával megszűrje, hogy mely dokumentum elérési útjait vegye fel vagy zárja ki az indexelésből.

Ha csak a szükséges útvonalakat indexeli, javíthatja az írási teljesítményt, csökkentheti az írási műveletek ru-költségeit, és csökkentheti az indextárolást olyan forgatókönyvek esetében, amelyekben korábban ismertek a lekérdezési minták. Ennek az az oka, hogy az indexelési költségek közvetlenül korrelálnak az indexelt egyedi útvonalak számával. Az alábbi kód például bemutatja, hogyan zárhatja ki a dokumentumok egy teljes szakaszát (egy részösszeget) az indexelésből a "*" helyettesítő karakterrel:

var containerProperties = new ContainerProperties(id: "excludedPathCollection", partitionKeyPath: "/pk" );
containerProperties.IndexingPolicy.IncludedPaths.Add(new IncludedPath { Path = "/*" });
containerProperties.IndexingPolicy.ExcludedPaths.Add(new ExcludedPath { Path = "/nonIndexedContent/*");
Container container = await this.cosmosDatabase.CreateContainerAsync(containerProperties);

További információ: Azure Cosmos DB indexelési szabályzatok.

Átfutás

Alacsonyabb RU/s-használat mérése és finomhangolása

Az Azure Cosmos DB számos adatbázisműveletet kínál. Ezek a műveletek közé tartoznak a relációs és hierarchikus lekérdezések univerzális lemezformátumú (UDF)-fájlokkal, tárolt eljárásokkal és eseményindítókkal, amelyek az adatbázis-gyűjtemény dokumentumain működnek.

Az egyes műveletekhez kapcsolódó költségek a művelet végrehajtásához szükséges processzortól, I/O-tól és memóriától függően változnak. A hardvererőforrások átgondolása és kezelése helyett egyetlen mértékként tekinthet a kérelemegységekre a különböző adatbázis-műveletek végrehajtásához és az alkalmazáskérelmek kiszolgálásához szükséges erőforrásokhoz.

Az átviteli sebesség az egyes tárolókhoz beállított kérelemegységek száma alapján van kiépítve. A kérelemegység-felhasználás másodpercenkénti egységárként lesz kiértékelve. A tárolóhoz kiosztott kérelemegység-mértéket meghaladó alkalmazások korlátozottak, amíg a sebesség nem csökken a tárolóhoz kiosztott szint alá. Ha az alkalmazás magasabb átviteli sebességet igényel, további kérelemegységek kiépítésével növelheti az átviteli sebességet.

A lekérdezés összetettsége hatással van arra, hogy egy művelethez hány kérelemegység szükséges. A predikátumok száma, a predikátumok jellege, az UDF-fájlok száma és a forrásadatkészlet mérete mind befolyásolják a lekérdezési műveletek költségeit.

Bármely művelet (létrehozás, frissítés vagy törlés) többletterhelésének méréséhez vizsgálja meg az x-ms-request-charge fejlécet (vagy a .NET SDK-ban ResourceResponse<T> vagy FeedResponse<T> annak megfelelő RequestCharge tulajdonságát) a műveletek által felhasznált kérelemegységek számának méréséhez:

// Measure the performance (Request Units) of writes
ItemResponse<Book> response = await container.CreateItemAsync<Book>(myBook, new PartitionKey(myBook.PkValue));
Console.WriteLine("Insert of item consumed {0} request units", response.RequestCharge);
// Measure the performance (Request Units) of queries
FeedIterator<Book> queryable = container.GetItemQueryIterator<ToDoActivity>(queryString);
while (queryable.HasMoreResults)
    {
        FeedResponse<Book> queryResponse = await queryable.ExecuteNextAsync<Book>();
        Console.WriteLine("Query batch consumed {0} request units", queryResponse.RequestCharge);
    }

Az ebben a fejlécben visszaadott kérelemdíj a kiosztott átviteli sebesség töredéke (azaz 2000 RU/s). Ha például az előző lekérdezés 1000 1 KB dokumentumot ad vissza, a művelet költsége 1000. Így egy másodpercen belül a kiszolgáló csak két ilyen kérést tart tiszteletben, mielőtt korlátozza a későbbi kéréseket. További információ: Kérelemegységek és a kérelemegység-kalkulátor.

Túl nagy sebességkorlátozás/kérési sebesség kezelése

Amikor egy ügyfél megkísérli túllépni egy fiók fenntartott átviteli sebességét, a kiszolgálón nincs teljesítménycsökkenés, és az átviteli sebesség nem használható a fenntartott szinten túl. A kiszolgáló előre befejezi a kérést a RequestRateTooLarge (HTTP-állapotkód: 429). Egy x-ms-retry-after-ms fejlécet ad vissza, amely azt jelzi, hogy ezredmásodpercben mennyi időt kell várnia a felhasználónak a kérés ismételt megkísérlése előtt.

    HTTP Status 429,
    Status Line: RequestRateTooLarge
    x-ms-retry-after-ms :100

Az SDK-k implicit módon elkapják ezt a választ, tiszteletben tartják a kiszolgáló által megadott újrapróbálkozási fejlécet, és újrapróbálkoznak a kéréssel. Ha a fiókját nem éri el egyszerre több ügyfél, a következő újrapróbálkozás sikeres lesz.

Ha több ügyfél kumulatív működése következetesen meghaladja a kérések arányát, előfordulhat, hogy az ügyfél által jelenleg 9-re beállított alapértelmezett újrapróbálkozási szám nem elegendő. Ebben az esetben az ügyfél egy CosmosException 429-s állapotkódot ad az alkalmazásnak.

Az alapértelmezett újrapróbálkozás számát a példány beállításával RetryOptionsCosmosClientOptions módosíthatja. Alapértelmezés szerint a 429-es állapotkódú CosmosException 30 másodperces kumulatív várakozási idő után lesz visszaadva, ha a kérés továbbra is a kérési sebesség felett működik. Ezt a hibát akkor is visszaadja a rendszer, ha az újrapróbálkozás aktuális száma kisebb, mint a maximális újrapróbálkozás száma, függetlenül attól, hogy az aktuális érték az alapértelmezett érték 9 vagy egy felhasználó által megadott érték.

Az automatikus újrapróbálkozási viselkedés segít a legtöbb alkalmazás rugalmasságának és használhatóságának javításában. De lehet, hogy nem ez a legjobb viselkedés, ha teljesítménymutatókat végez, különösen akkor, ha a késést méri. Az ügyfél által megfigyelt késés megnő, ha a kísérlet eléri a kiszolgálót, és az ügyfél SDK-jának csendes újrapróbálkozását okozza. A teljesítménykísérletek során fellépő késési csúcsok elkerülése érdekében mérje meg az egyes műveletek által visszaadott díjat, és győződjön meg arról, hogy a kérések a fenntartott kérések aránya alatt működnek.

További információ: Kérelemegységek.

A nagyobb átviteli sebesség érdekében kisebb dokumentumok tervezése

Egy adott művelet kérelemdíja (azaz a kérelemfeldolgozási költség) közvetlenül a dokumentum méretével függ össze. A nagyméretű dokumentumokon végzett műveletek többe kerülnek, mint a kis méretű dokumentumokon végzett műveletek.

Következő lépések

Az Azure Cosmos DB néhány ügyfélgépen történő nagy teljesítményű forgatókönyvek kiértékeléséhez használt mintaalkalmazásért tekintse meg az Azure Cosmos DB teljesítmény- és méretezési tesztelését.

Ha többet szeretne megtudni az alkalmazás méretezéshez és nagy teljesítményhez való tervezéséről, tekintse meg a particionálást és a skálázást az Azure Cosmos DB-ben.