A Node.js-t villámgyors teljesítményéről ismerjük. Mégis, mint minden nyelv esetében, írhatunk olyan Node.js kódot, amely rosszabbul teljesít a felhasználók számára, mint szeretnénk. Ennek leküzdéséhez megfelelő teljesítménytesztelésre van szükségünk. Ma éppen ezzel foglalkozunk, és részletesen megvizsgáljuk, hogyan állíthatunk be és futtathatunk teljesítménytesztet, és elemezhetjük az eredményeket, hogy villámgyors Node.js alkalmazásokat készíthessünk.

A legjobb módja annak, hogy megértsük, hogyan teszteljük az alkalmazásunk teljesítményét, ha végigmegyünk egy példán.

A Node.js-t számos célra használhatjuk: szkriptek írására feladatok futtatásához, webszerver futtatására vagy statikus fájlok, például egy weboldal kiszolgálására. Ma egy Node.js HTTP webes API tesztelésének lépéseit fogjuk végigjárni. De ha valami mást építesz Node-ban, ne aggódj – az elvek nagy része hasonló lesz.

A Node.js teljesítményének egyedi jellege

Mielőtt elkezdenénk, vessünk egy gyors pillantást a Node.js teljesítményének egyik egyedi jellemzőjére. Ezeknek a jellemzőknek az ismeretére később szükségünk lesz, amikor a teljesítménytesztjeinket futtatjuk.

Miről beszélek?

A Node.js alkalmazások nagy szempontja az egyszálas, a befejezéstől a befejezésig tartó viselkedésük – amit az úgynevezett eseményhurok segít elő. Most tudom, mire gondolsz: ez sok. Szóval bontsuk le egy kicsit, hogy megértsük, mit jelentenek ezek.

Kezdjük az egyszálúsággal. A szálkezelés, mint fogalom, lehetővé teszi az egyidejű feldolgozást egy alkalmazáson belül. A Node.js nem rendelkezik ezzel a képességgel, legalábbis nem a hagyományos értelemben. Ehelyett a több feladatot egyszerre végrehajtó alkalmazások írásához ott van az aszinkron kód és az eseményhurok.

Az eseményhurok

Mi az az eseményhurok?

Az eseményhurok a Node.js módja a hosszú futású folyamatok kis darabokra bontására. Úgy működik, mint a szívverés: Néhány ezredmásodpercenként a Node.js ellenőrzi a munkasorozatot, hogy új feladatokat indítson. Ha van munka, akkor ezeket felviszi a hívási veremre, majd lefuttatja őket a befejezésig (a run-to-completionról hamarosan beszélünk).

A feladatok lebontásával a Node.js képes a multi-taskolásra, ami a szálak helyettesítését jelenti. Ez azt jelenti, hogy amíg az egyik feladat várakozik, addig egy másik elindulhat. Tehát a szálkezelés helyett aszinkron kódot használunk, amit olyan programozási stílusok könnyítenek meg, mint a callbackek, ígéretek és az async/await. A legtöbb out-of-the-box Node API mind szinkron, mind aszinkron végrehajtási módszerrel rendelkezik.

Oké, most talán azon tűnődik: mi köze van ennek a sok techno-zsargonnak a teljesítményhez?

Hadd magyarázzam el…

Node.js teljesítmény és az eseményhurok

Tegyük fel, hogy egy Node.js alkalmazást építesz két végponttal: egy a fájlfeltöltéshez, és egy a felhasználói profil lekéréséhez. A felhasználói profil API-t valószínűleg jóval gyakrabban fogják kérni, mint a fájlfeltöltést, és ha nem reagál elég gyorsan, akkor minden felhasználó számára blokkolni fog minden oldalbetöltést – ez nem jó.

A felhasználói feltöltési API-t ritkán használják. Emellett a felhasználók elvárják, hogy a feladatok feltöltése időt vegyen igénybe, de sokkal kevésbé elnézőek az oldal betöltési idejével kapcsolatban. Ha nem az eseményhurok figyelembevételével programozunk, miközben a fájl feltöltése zajlik, a Node.js a végén az összes rendszererőforrást lefoglalhatja, és megakadályozhatja, hogy más felhasználók használhassák az alkalmazásunkat-uh-oh!

És ezért kell megértenünk a Node.js egyszálúságát. Ahogy változtatunk az alkalmazásunkon, figyelembe kell vennünk ezt a viselkedést. El akarjuk kerülni, hogy szinkronban végezzünk hosszú futású feladatokat, például hálózati kéréseket, fájlok írását vagy nehéz számításokat.

Most már ismerjük a Node.js egyszálú természetét, és kihasználhatjuk az előnyünkre. Lássuk lépésről lépésre, hogyan állíthatjuk be, futtathatjuk és elemezhetjük a Node.js alkalmazásunk teljesítménytesztjét, hogy megbizonyosodjunk arról, hogy a lehető legjobban kihasználjuk a Node.js teljesítményképességeit.

1. lépés: A Node.js teljesítménytesztelő eszköz kiválasztása

Először is ki kell választanunk egy olyan eszközt, amely lehetővé teszi a teljesítménytesztek futtatását. Számos eszköz létezik, mindegyiknek különböző előnyei és hátrányai vannak a Node.js teljesítményhangolásához. Az egyik legfontosabb dolog, amit figyelembe kell venned, hogy bár egy Node.js alkalmazást tesztelsz, ha a teljesítményt a külvilágból egy hálózaton keresztül fogod tesztelni, nem számít, hogy a teljesítménytesztelő eszközöd Node.js-ben íródott-e.

Az alapvető HTTP teljesítményteszteléshez én az Artillery-t szeretem, egy egyszerű, Node.js-ben írt teljesítménytesztelő eszközt. Különösen jó az API-kérések teljesítménytesztjeinek futtatására is. Az Artillery úgy működik, hogy egy konfigurációs fájlt írunk, amely meghatározza a terhelési profilunkat. Megmondod az Artillery-nek, hogy mely végpontokat szeretnéd kérni, milyen sebességgel, milyen időtartamra, stb.

Egy alapvető tesztszkript így néz ki:

config: target: 'https://artillery.io' phases: - duration: 60 arrivalRate: 20 defaults: headers: x-my-service-auth: '987401838271002188298567'scenarios:- flow:- get:url: "/docs"

Itt az Artillery weboldalát kérdezed le 60 másodpercig, miközben 20 új felhasználó érkezik az URL-re.

Ezután a teszt futtatásához egyszerűen végrehajtja:

artillery run your_config.yml

Az Artillery annyi kérést intéz az alkalmazásodhoz, amennyit utasítottál. Ez hasznos a termelési környezetet utánzó teljesítményteszt-profilok létrehozásához. Mit értek teljesítménytesztprofil alatt? Ezzel most foglalkozzunk.

2. lépés: Node.js teljesítményteszt-profil létrehozása

A teljesítményteszt-profil, mint fentebb, egy definíció arra vonatkozóan, hogyan fog futni a teljesítményteszted. A pontos Node.js teljesítményhangoláshoz lehetőleg azt szeretné utánozni, ahogyan a termelési forgalom viselkedik vagy várhatóan viselkedni fog. Például, ha egy esemény-weboldalt épít, akkor a jegyek kiadásának idején nagy forgalomra számíthat, ezért olyan profilt kell készítenie, amely ezt a viselkedést utánozza. Szeretnéd tesztelni, hogy az alkalmazásod képes-e rövid idő alatt nagy mennyiségű terheléssel skálázódni. Alternatívaként, ha e-kereskedelmi webhelyet üzemeltet, egyenletes forgalomra számíthat. Itt a teljesítményteszt-profiljainak ezt a viselkedést kell tükrözniük.

Több tesztprofil kihasználása

Egy szórakoztató és érdekes dolog, hogy különböző tesztprofilokat hozhat létre, és azokat átfedő módon futtathatja. Például létrehozhat egy olyan profilt, amely az alapszintű forgalmat utánozza – mondjuk 100 kérést percenként -, majd utánozhatja, mi történhet, ha nagy forgalom érkezik az oldalára, mondjuk ha keresőmotoros hirdetéseket tesz ki. A többféle forgatókönyv tesztelése fontos az alapos Node.js teljesítményhangoláshoz.

Nagyméretű elosztott rendszerek replikálása

Egy pillanatra meg kell itt jegyeznem valamit: Amikor egy alkalmazás elér egy bizonyos méretet, a terhelés ilyen módon történő utánzása elveszti megvalósíthatóságát. A forgalom volumene olyan vad, kiszámíthatatlan vagy nagy volumenű lehet, hogy nehéz reális hasonlót létrehozni az alkalmazás tesztelésére a kiadás előtt.

De mi van, ha ez a helyzet? Mit tegyünk? Tesztelünk a gyártásban.

Elképzelhető, hogy azt gondolja: “Hú, várjunk csak! Nem a kiadás előtt kellene tesztelnünk?”

Megtehetjük, de amikor egy rendszer elér egy bizonyos méretet, akkor lehet, hogy érdemes más teljesítménytesztelési stratégiákat kihasználni. Olyan koncepciókat használhatsz ki, mint a canary releasing, hogy a változtatásokat kiadod a termelésbe, és csak a felhasználók egy bizonyos százalékával teszteled őket. Ha teljesítménycsökkenést tapasztal, akkor a forgalmat visszacserélheti a korábbi implementációra. Ez a folyamat valóban ösztönzi a kísérletezést, és a legjobb része az, hogy a valódi termelési alkalmazáson tesztel, így nem kell aggódnia amiatt, hogy a teszteredmények nem utánozzák a termelést.

Eddáig döntöttünk az eszközeinkről, és létrehoztuk a termelésünket újraalkotó profilokat, például a forgalmat és a munkaterhelést. Mi a következő lépés? Biztosítanunk kell, hogy rendelkezzünk az alkalmazásunk elemzéséhez szükséges adatokkal, és ezt a Node.js teljesítményfigyelő és az Application Performance Management (APM) eszközökkel tehetjük meg. Mi az az APM? Olvass tovább, és elmondom!

3. lépés: Állítsuk be a megfigyelhetőséget/megfigyelést

Nem akarjuk csak futtatni a teljesítménytesztünket az alkalmazásunkkal szemben, és csak reménykedni és imádkozni. Ha ezt tesszük, nem fogjuk tudni megérteni, hogyan teljesít, és hogy azt teszi-e, amit gondolunk, hogy tennie kellene. Mielőtt tehát elkezdenénk, fel kell tennünk magunknak olyan kérdéseket, mint például: “Az én alkalmazásom esetében hogyan néz ki a jó teljesítmény? Mik az SLA-k és KPI-k? Milyen mérőszámokra van szükség a teljesítményprobléma hatékony hibakereséséhez?”

Ha az alkalmazásunk lassan vagy a várttól eltérően teljesít, adatokra lesz szükségünk, hogy megértsük, miért, így javíthatunk rajta. Minden valamirevaló termelő alkalmazás valamilyen megfigyelhetőségi és/vagy felügyeleti megoldást használ. Ezek az eszközök, amelyeket gyakran APM-nek neveznek, lehetővé teszik a futó alkalmazásod kritikus Node.js teljesítményméréseinek megtekintését.

Az APM bevezetése és használata

A APM-ek különböző formákban és méretekben léteznek, mind különböző funkciókkal, árcédulákkal, biztonsági vonatkozásokkal, teljesítménnyel, amit csak akarsz. Érdemes egy kicsit körülnézni, hogy megtaláljuk az igényeinknek legmegfelelőbb eszközt. Ezek az eszközök azok, amelyek a Node.js teljesítménytesztek futtatásakor a szükséges betekintést és adatokat fogják nyújtani számunkra.

Szóval, ha tudjuk, hogy monitoroznunk kell az alkalmazásunkat – pontosan mit is kellene monitoroznunk?

Igazából a lehető legtöbb adatot szeretnénk – de bármennyire is szeretjük az adatokat; reálisan kell látnunk, hol kezdjük! A legjobb, ha a következő három területtel kezdjük:

  • Összesített naplók-Az alkalmazásnaplókat vagy implicit módon bocsátja ki néhány könyvtár, vagy explicit módon a fejlesztő, hogy betekintést nyerjen az alkalmazásba. A legtöbb aggregált naplóeszköz lehetővé teszi a naplózott adatok egyszerű keresését és vizualizálását. A mi esetünkben az egyes API-k teljesítményét naplózhatjuk ki, és ábrázolhatjuk őket egy grafikonon.
  • Infrastruktúra betekintés-Az alkalmazásunk többféle tárhelyen fog futni, ezért valószínűleg az összes adatot látni szeretné. Ha felhőben futtatja, a legtöbb szolgáltató ezeket az adatokat (bár nyers formában) azonnal megadja. Az adatok, amelyeket ezektől az eszközöktől kaphat, olyan dolgokra terjednek ki, mint a hoszt CPU- és memóriahasználata, kapcsolati adatok stb.
  • Alkalmazásfigyelés – Ez a fajta eszköz általában az alkalmazáskódon belül helyezkedik el, és betekintést nyerhet abba, hogy a funkciók hogyan teljesítenek/hívódnak, milyen hibákat dobunk, stb.

Egyes APM-eszközök, például a Retrace, e három funkció mindegyikét vagy többségét egybefoglalják, míg mások sokkal specializáltabbak lehetnek. Az igényeinktől függően lehet, hogy egy eszközre van szükségünk, amely mindent csinál, vagy egy egész sor eszközre különböző célokra.

Node.js-re szabott eszközök

Az eszközökön felül más Node.js-specifikus eszközöket és profilozókat is bevonhatunk, mint például a flame graphs, amelyek megnézik a függvényeink végrehajtását, vagy adatokat nyernek az eseményhurok végrehajtásáról. Ahogy egyre jobban beleássuk magunkat a Node.js teljesítménytesztelésébe, az adatigényünk is csak növekedni fog. Folyamatosan szeretne majd vásárolni, kísérletezni és frissíteni az eszközeinket, hogy valóban megértsük az alkalmazásunkat.

Most, hogy beállítottuk az eszközeinket, reális profilokat kaptunk a teljesítményünkhöz, és megértettük az alkalmazásunk teljesítményét, már majdnem készen állunk a tesztek futtatására. De mielőtt ezt megtennénk, van még egy lépés: a tesztinfrastruktúra létrehozása.

4. lépés: Node.js teljesítményteszt-infrastruktúra létrehozása

A teljesítményteszteket a saját gépünkről is futtathatjuk, ha szeretnénk, de vannak ezzel kapcsolatos problémák. Eddig nagyon keményen próbáltuk – például a tesztprofilokkal – biztosítani, hogy a teljesítménytesztjeink replikálódjanak. A tesztjeink replikálásának másik tényezője, hogy mindig ugyanazon az infrastruktúrán (értsd: gépen) futtassuk őket.

A konzisztens tesztinfrastruktúra elérésének egyik legegyszerűbb módja a felhőalapú tárhely kihasználása. Válasszon ki egy hosztot/gépet, ahonnan a tesztjeit indítani szeretné, és biztosítsa, hogy minden egyes alkalommal, amikor a tesztjeit futtatja, mindig ugyanarról a gépről – és lehetőleg ugyanarról a helyről is – futtassa, hogy elkerülje az adatok torzítását a kérés késleltetése alapján.

Ezt az infrastruktúrát érdemes szkriptelni, hogy szükség szerint létrehozhassa és lebonthassa. Ezt az ötletet “infrastruktúra mint kód” néven emlegetik. A legtöbb felhőszolgáltató natívan támogatja ezt, vagy egy olyan eszközzel, mint a Terraform, segíthet ebben.

Fú! Eddig sok mindent megtettünk, és elérkeztünk az utolsó lépéshez: a tesztek futtatásához.

5. lépés: Futtassuk a teszteket!

Az utolsó lépés a tesztek tényleges futtatása. Ha elindítjuk a parancssori konfigurációnkat (ahogy az 1. lépésben tettük), látni fogjuk a Node.js alkalmazásunkhoz érkező kéréseket. A felügyeleti megoldásunkkal ellenőrizhetjük, hogy az eseményhurok hogyan teljesít, hogy bizonyos kérések hosszabb ideig tartanak-e, mint mások, hogy a kapcsolatok időzítettek-e, stb.

A teljesítménytesztek hab a tortán, ha megfontoljuk, hogy beépítsük őket a build- és tesztelési csővezetékünkbe. Ennek egyik módja, hogy a teljesítménytesztjeit éjszakára futtatja, így minden reggel felülvizsgálhatja őket. Az Artillery egy szép, egyszerű módot biztosít ezeknek a jelentéseknek a létrehozására, amelyek segíthetnek észrevenni a Node.js teljesítményregresszióit.

Most már villámgyors Node.js

Ez a csomag.

A mai napon áttekintettük az eseményhurok jelentőségét a JavaScript-alkalmazásod teljesítménye szempontjából, hogyan válaszd ki a teljesítménytesztelési eszközeidet, hogyan állíthatsz be konzisztens teljesítményteszt-profilokat az Artillery segítségével, milyen monitorozást érdemes beállítanod a Node.js teljesítményproblémák diagnosztizálására, és végül, hogyan és mikor futtassa a teljesítményteszteket, hogy a legtöbbet hozza ki magából és a csapatából.

Kísérletezzen olyan felügyeleti eszközökkel, mint a Retrace APM for Node.js, végezzen apró változtatásokat, hogy tesztelni tudja a változtatások hatását, és gyakran nézze át a tesztjelentéseket, hogy észrevegye a regressziókat. Most már mindened megvan ahhoz, hogy kihasználd a Node.js teljesítményképességeit, és szuper teljesítményű alkalmazást írj, amit a felhasználóid imádnak!

Vélemény, hozzászólás?

Az e-mail-címet nem tesszük közzé.