Ez a cikk azt ismerteti, hogy egy fejlesztői csapat hogyan használt metrikákat a szűk keresztmetszetek megtalálásához és az elosztott rendszerek teljesítményének javításához. A cikk egy mintaalkalmazás tényleges terheléstesztjén alapul. Az alkalmazás a mikroszolgáltatások Azure Kubernetes Service (AKS) alapkonfigurációjából, valamint az eredmények létrehozásához használt Visual Studio terheléstesztelési projektből származik.
Ez a cikk egy sorozat része. Olvassa el az első részt itt.
Forgatókönyv: Hívjon meg több háttérszolgáltatást az információk lekéréséhez, majd összesítse az eredményeket.
Ez a forgatókönyv egy drónkézbesítési alkalmazást is magában foglal. Az ügyfelek lekérdezhetnek egy REST API-t a legújabb számlaadatok lekéréséhez. A számla tartalmazza az ügyfél szállításainak, csomagjainak és a drónok teljes kihasználtságának összegzését. Ez az alkalmazás egy AKS-en futó mikroszolgáltatás-architektúrát használ, és a számlához szükséges információk több mikroszolgáltatásra is kiterjednek.
Ahelyett, hogy az ügyfél közvetlenül hívja meg az egyes szolgáltatásokat, az alkalmazás implementálja az átjáró-összesítési mintát. Ezzel a mintával az ügyfél egyetlen kérést küld egy átjárószolgáltatásnak. Az átjáró ezzel párhuzamosan meghívja a háttérszolgáltatásokat, majd egyetlen válasz hasznos adattá összesíti az eredményeket.
1. teszt: Alapkonfiguráció teljesítménye
Az alapkonfiguráció kialakításához a fejlesztői csapat egy lépésbetöltési teszttel indult, amely egy szimulált felhasználótól 40 felhasználóig, összesen 8 perc alatt tette el a terhelést. A Visual Studióból vett alábbi diagram az eredményeket mutatja. A lila vonal a felhasználó terhelését, a narancssárga vonal pedig az átviteli sebességet (átlagos kérések másodpercenként) jeleníti meg.
A diagram alján látható piros vonal azt mutatja, hogy az ügyfél nem adott vissza hibát, ami biztató. Az átlagos átviteli sebesség azonban körülbelül félúton halad végig a teszten, majd a fennmaradó részre csökken, még akkor is, ha a terhelés folyamatosan növekszik. Ez azt jelzi, hogy a háttér nem tud lépést tartani. Az itt látható minta gyakori, amikor egy rendszer elkezdi elérni az erőforráskorlátokat – a maximális érték elérése után az átviteli sebesség ténylegesen jelentősen csökken. Az erőforrás-versengés, az átmeneti hibák vagy a kivételek számának növekedése mind hozzájárulhat ehhez a mintához.
Vizsgáljuk meg a monitorozási adatokat, hogy megtudjuk, mi történik a rendszerben. A következő diagram az Application Insightsból származik. Az átjáróról a háttérszolgáltatásokra irányuló HTTP-hívások átlagos időtartamát jeleníti meg.
Ez a diagram azt mutatja, hogy egy művelet, különösen , GetDroneUtilization
átlagosan sokkal tovább tart – nagyságrendekkel. Az átjáró párhuzamosan hajtja végre ezeket a hívásokat, így a leglassabb művelet határozza meg, hogy mennyi ideig tart a teljes kérés végrehajtása.
A következő lépés egyértelműen a művelet feltárása és a GetDroneUtilization
szűk keresztmetszetek keresése. Az egyik lehetőség az erőforrás-kimerülés. Lehet, hogy ez a háttérszolgáltatás elfogy a cpu-ból vagy a memóriából. Az AKS-fürtök esetében ezek az információk a Azure Portal érhetők el az Azure Monitor tárolóelemzési funkciójával. Az alábbi grafikonok az erőforrás-kihasználtságot mutatják a fürt szintjén:
Ebben a képernyőképen az átlag és a maximális érték is látható. Fontos, hogy ne csak az átlagot nézzük, mert az átlag elrejtheti a kiugró értékeket az adatokban. Itt az átlagos cpu-kihasználtság 50% alatt marad, de néhány kiugró érték 80%. Ez közel van a kapacitáshoz, de még mindig a tűréshatárokon belül van. Valami más okozza a szűk keresztmetszetet.
A következő diagramon a valódi bűnös látható. Ez a diagram a kézbesítési szolgáltatás háttéradatbázisából származó HTTP-válaszkódokat mutatja, amely ebben az esetben az Azure Cosmos DB. A kék vonal a sikerkódokat (HTTP 2xx), míg a zöld vonal a HTTP 429-es hibákat jelöli. A HTTP 429-es visszatérési kód azt jelenti, hogy az Azure Cosmos DB ideiglenesen szabályozza a kéréseket, mert a hívó a kiépítettnél több erőforrásegységet (RU) használ.
A további megállapítások érdekében a fejlesztői csapat az Application Insights segítségével a kérések reprezentatív mintáinak végpontok közötti telemetriáját tekintette meg. Íme egy példány:
Ez a nézet egyetlen ügyfélkéréshez kapcsolódó hívásokat, valamint időzítési információkat és válaszkódokat jelenít meg. A legfelső szintű hívások az átjárótól a háttérszolgáltatásokig vannak. A hívás GetDroneUtilization
kibontva jelenik meg a külső függőségekhez – ebben az esetben az Azure Cosmos DB-hez – irányuló hívások megjelenítéséhez. A pirossal jelzett hívás HTTP 429-hibát adott vissza.
Figyelje meg a HTTP 429-hiba és a következő hívás közötti nagy különbséget. Amikor az Azure Cosmos DB-ügyfélkódtár HTTP 429-re vonatkozó hibaüzenetet kap, automatikusan kikapcsol, és megvárja, amíg újra megkísérli a műveletet. Ez a nézet azt mutatja, hogy a művelet 672 ms-os időtartama alatt az idő nagy részét az Azure Cosmos DB újrapróbálkozására várták.
Íme egy másik érdekes grafikon ehhez az elemzéshez. A fizikai partíciónkénti ru-használatot és a fizikai partíciónként kiosztott kérelemegységeket jeleníti meg:
A gráf megértéséhez meg kell értenie, hogyan kezeli az Azure Cosmos DB a partíciókat. Az Azure Cosmos DB gyűjteményeinek partíciókulcsa is lehet. Minden lehetséges kulcsérték meghatározza a gyűjteményen belüli adatok logikai partícióját. Az Azure Cosmos DB ezeket a logikai partíciókat egy vagy több fizikai partíció között osztja el. A fizikai partíciók kezelését az Azure Cosmos DB automatikusan kezeli. Ha több adatot tárol, az Azure Cosmos DB áthelyezheti a logikai partíciókat új fizikai partíciókba, hogy a terhelést eloszthassa a fizikai partíciók között.
Ehhez a terhelési teszthez az Azure Cosmos DB-gyűjtemény 900 kérelemegységtel lett kiépítve. A diagram fizikai partíciónként 100 RU-t mutat, ami összesen kilenc fizikai partíciót jelent. Bár az Azure Cosmos DB automatikusan kezeli a fizikai partíciók horizontális felosztását, a partíciók számának ismerete betekintést nyújthat a teljesítménybe. A fejlesztői csapat ezt az információt később fogja használni, mivel továbbra is optimalizálni fogják. Ha a kék vonal átlépi a lila vízszintes vonalat, a kérelemegység-használat túllépte a kiosztott kérelemegységeket. Ez az a pont, ahol az Azure Cosmos DB megkezdi a hívások szabályozását.
2. teszt: Erőforrásegységek növelése
A második terheléses teszt során a csapat 900 RU-ról 2500 RU-ra skálázta fel az Azure Cosmos DB-gyűjteményt. Az átviteli sebesség 19 kérelemről másodpercenként 23 kérelemre/másodpercre nőtt, és az átlagos késés 669 ms-ról 569 ms-ra csökkent.
Metrika | 1\. teszt | 2\. teszt |
---|---|---|
Átviteli sebesség (req/sec) | 19 | 23 |
Átlagos késés (ms) | 669 | 569 |
Sikeres kérések | 9,8 K | 11 K |
Ezek nem hatalmas nyereségek, de ha az idő múlásával nézzük a grafikont, teljesebb képet láthatunk:
Míg az előző teszt kezdeti kiugrást, majd éles csökkenést mutatott, ez a teszt konzisztensebb átviteli sebességet mutat. A maximális átviteli sebesség azonban nem lényegesen magasabb.
Az Azure Cosmos DB-nek küldött összes kérés 2xx állapotot adott vissza, és a HTTP 429-hibák eltűntek:
A kérelemegység-használat és a kiosztott kérelemegységek grafikonja azt mutatja, hogy rengeteg a fejtér. Fizikai partíciónként körülbelül 275 kérelemegység van, és a terhelési teszt másodpercenként körülbelül 100 kérelemegységre tetőzött.
Egy másik érdekes metrika az Azure Cosmos DB-be irányuló hívások száma sikeres műveletenként:
Metrika | 1\. teszt | 2\. teszt |
---|---|---|
Hívások műveletenként | 11 | 9 |
Ha nem történik hiba, a hívások számának meg kell egyeznie a tényleges lekérdezési tervvel. Ebben az esetben a művelet egy partíciók közötti lekérdezést tartalmaz, amely mind a kilenc fizikai partíciót eléri. Az első terhelési teszt magasabb értéke a 429-es hibát eredményező hívások számát tükrözi.
Ezt a metrikát egy egyéni Log Analytics-lekérdezés futtatásával számítottuk ki:
let start=datetime("2020-06-18T20:59:00.000Z");
let end=datetime("2020-07-24T21:10:00.000Z");
let operationNameToEval="GET DroneDeliveries/GetDroneUtilization";
let dependencyType="Azure DocumentDB";
let dataset=requests
| where timestamp > start and timestamp < end
| where success == true
| where name == operationNameToEval;
dataset
| project reqOk=itemCount
| summarize
SuccessRequests=sum(reqOk),
TotalNumberOfDepCalls=(toscalar(dependencies
| where timestamp > start and timestamp < end
| where type == dependencyType
| summarize sum(itemCount)))
| project
OperationName=operationNameToEval,
DependencyName=dependencyType,
SuccessRequests,
AverageNumberOfDepCallsPerOperation=(TotalNumberOfDepCalls/SuccessRequests)
Összefoglalva, a második terhelési teszt javulást mutat. A GetDroneUtilization
művelet azonban nagyságrendekkel tovább tart, mint a következő leglassabb művelet. A végpontok közötti tranzakciók megvizsgálása segít megmagyarázni, hogy miért:
Ahogy korábban említettük, a GetDroneUtilization
művelet egy keresztpartíciós lekérdezést tartalmaz az Azure Cosmos DB-nek. Ez azt jelenti, hogy az Azure Cosmos DB-ügyfélnek minden fizikai partícióra ki kell bontania a lekérdezést, és be kell gyűjtenie az eredményeket. Ahogy a teljes körű tranzakció nézet mutatja, ezeket a lekérdezéseket soros módon hajtja végre a rendszer. A művelet mindaddig tart, amíg az összes lekérdezés összege megtelik – és ez a probléma csak az adatok méretének növekedésével és további fizikai partíciók hozzáadásával lesz rosszabb.
3. teszt: Párhuzamos lekérdezések
Az előző eredmények alapján a késés csökkentésének nyilvánvaló módja a lekérdezések párhuzamos kiadása. Az Azure Cosmos DB ügyféloldali SDK olyan beállítással rendelkezik, amely a párhuzamosság maximális fokát szabályozza.
Érték | Leírás |
---|---|
0 | Nincs párhuzamosság (alapértelmezett) |
> 0 | Párhuzamos hívások maximális száma |
-1 | Az ügyféloldali SDK optimális párhuzamossági fokot választ |
A harmadik terheléses teszt esetében ez a beállítás 0-ról -1-re módosult. Az alábbi táblázat összefoglalja az eredményeket:
Metrika | 1\. teszt | 2\. teszt | 3. teszt |
---|---|---|---|
Átviteli sebesség (req/sec) | 19 | 23 | 42 |
Átlagos késés (ms) | 669 | 569 | 215 |
Sikeres kérések | 9,8 K | 11 K | 20 K |
Szabályozott kérelmek | 2.72 K | 0 | 0 |
A terhelésvizsgálati grafikonon nem csak a teljes átviteli sebesség sokkal magasabb (a narancssárga vonal), hanem az átviteli sebesség is lépést tart a terheléssel (a lila vonallal).
A végpontok közötti tranzakciónézet megtekintésével ellenőrizheti, hogy az Azure Cosmos DB-ügyfél párhuzamosan végez-e lekérdezéseket:
Érdekes, hogy az átviteli sebesség növelésének egyik mellékhatása, hogy a másodpercenként felhasznált kérelemegységek száma is növekszik. Bár az Azure Cosmos DB nem hajtotta le a kéréseket a teszt során, a használat megközelítette a kiosztott RU-korlátot:
Ez a gráf jelezheti az adatbázis további felskálázását. Kiderült azonban, hogy ehelyett optimalizálhatjuk a lekérdezést.
4. lépés: A lekérdezés optimalizálása
Az előző terhelési teszt jobb teljesítményt mutatott a késés és az átviteli sebesség tekintetében. A kérelmek átlagos késése 68%-kal csökkent, és az átviteli sebesség 220%-kal nőtt. A partíciók közötti lekérdezés azonban aggodalomra ad okot.
A partíciók közötti lekérdezésekkel az a probléma, hogy minden partíción fizetnie kell az RU-ért. Ha a lekérdezés csak alkalmanként fut – mondjuk óránként egyszer – nem számít. Ha azonban olyan nagy olvasási terhelést lát, amely több partíciós lekérdezést is magában foglal, látnia kell, hogy a lekérdezés optimalizálható-e egy partíciókulcs használatával. (Előfordulhat, hogy át kell terveznie a gyűjteményt egy másik partíciókulcs használatához.)
Az alábbi lekérdezés az adott forgatókönyvhöz készült:
SELECT * FROM c
WHERE c.ownerId = <ownerIdValue> and
c.year = <yearValue> and
c.month = <monthValue>
Ez a lekérdezés egy adott tulajdonosazonosítónak és hónap/év rekordnak megfelelő rekordokat választ ki. Az eredeti kialakításban ezen tulajdonságok egyike sem a partíciókulcs. Ehhez az ügyfélnek ki kell bontania a lekérdezést az egyes fizikai partíciókra, és összegyűjtenie az eredményeket. A lekérdezési teljesítmény javítása érdekében a fejlesztői csapat módosította a tervet, hogy a tulajdonos azonosítója legyen a gyűjtemény partíciókulcsa. Így a lekérdezés egy adott fizikai partíciót célozhat meg. (Az Azure Cosmos DB ezt automatikusan kezeli, nem kell kezelnie a partíciókulcs-értékek és a fizikai partíciók közötti leképezést.)
Miután a gyűjteményt az új partíciókulcsra váltotta, jelentősen javult az RU-használat, ami közvetlenül alacsonyabb költségekkel jár.
Metrika | 1\. teszt | 2\. teszt | 3. teszt | 4. teszt |
---|---|---|---|---|
Kérelemegységek műveletenként | 29 | 29 | 29 | 3.4 |
Hívások műveletenként | 11 | 9 | 10 | 1 |
A végpontok közötti tranzakció nézet azt mutatja, hogy az előrejelzett módon a lekérdezés csak egy fizikai partíciót olvas be:
A terhelési teszt jobb átviteli sebességet és késést mutat:
Metrika | 1\. teszt | 2\. teszt | 3. teszt | 4. teszt |
---|---|---|---|---|
Átviteli sebesség (req/sec) | 19 | 23 | 42 | 59 |
Átlagos késés (ms) | 669 | 569 | 215 | 176 |
Sikeres kérések | 9,8 K | 11 K | 20 K | 29 K |
Szabályozott kérelmek | 2.72 K | 0 | 0 | 0 |
A jobb teljesítmény egyik következménye, hogy a csomópont cpu-kihasználtsága nagyon magas lesz:
A terhelési teszt vége felé az átlagos processzorhasználat elérte a 90%-ot, a maximális processzorhasználat pedig elérte a 100%-ot. Ez a metrika azt jelzi, hogy a cpu a rendszer következő szűk keresztmetszete. Ha nagyobb átviteli sebességre van szükség, a következő lépés a kézbesítési szolgáltatás további példányokra való horizontális felskálázása lehet.
Összefoglalás
Ebben a forgatókönyvben a következő szűk keresztmetszeteket azonosítottuk:
- Az Azure Cosmos DB szabályozási kérései a kiosztott kérelemegységek elégtelensége miatt.
- Nagy késést okozott több adatbázispartíció soros lekérdezése.
- Nem hatékony partícióközi lekérdezés, mert a lekérdezés nem tartalmazza a partíciókulcsot.
Emellett a processzorhasználatot nagyobb léptékben is lehetséges szűk keresztmetszetként azonosították. A problémák diagnosztizálásához a fejlesztői csapat a következő szempontokat vizsgálta:
- Késés és átviteli sebesség a terhelési tesztből.
- Azure Cosmos DB-hibák és ru-használat.
- A végpontok közötti tranzakció nézet az Application Insightsban.
- Processzor- és memóriakihasználtság az Azure Monitor tárolóelemzéseiben.
Következő lépések
Teljesítményelhárítók áttekintése