We kennen Node.js om zijn bliksemsnelle prestaties. Toch, zoals met elke taal, kun je Node.js code schrijven die slechter presteert voor je gebruikers dan je zou willen. Om dit te bestrijden, moeten we adequate performance testen. Vandaag zullen we precies dat behandelen met een diepgaande blik op hoe je een performancetest kunt opzetten en uitvoeren en de resultaten kunt analyseren, zodat je bliksemsnelle Node.js-toepassingen kunt maken.
De beste manier om te begrijpen hoe je je toepassing kunt performancetesten, is door een voorbeeld te doorlopen.
Je kunt Node.js voor veel doeleinden gebruiken: het schrijven van scripts voor het uitvoeren van taken, het uitvoeren van een webserver, of het serveren van statische bestanden, zoals een website. Vandaag lopen we door de stappen om een Node.js HTTP web API te testen. Maar als je iets anders bouwt in Node, maak je geen zorgen – veel van de principes zullen vergelijkbaar zijn.
- De unieke aard van Node.js performance
- De event loop
- Node.js performance en de event loop
- Stap 1: Node.js-prestatietesttooling kiezen
- Stap 2: Maak een Node.js performance test profiel
- Gebruik maken van meerdere test profielen
- Repliceren van grootschalige gedistribueerde systemen
- Stap 3: Stel je observeerbaarheid/monitoring in
- Aan de slag met een APM
- Tooling toegesneden op Node.js
- Stap 4: Maak Node.js performance test infrastructuur
- Stap 5: Voer uw tests uit!
- Nu heb je bliksemsnelle Node.js
De unieke aard van Node.js performance
Voordat we beginnen, laten we een snelle blik werpen op een van de meer unieke kenmerken van Node.js performance. We zullen later kennis van deze kenmerken nodig hebben wanneer we onze prestatietests uitvoeren.
Waar heb ik het over?
De grote overweging voor Node.js-toepassingen is hun single-threaded, run-to-completion-gedrag-gefaciliteerd door wat bekend staat als de event-lus. Nu, ik weet wat je denkt: dat is veel. Dus laten we dit een beetje uit elkaar halen, zodat we begrijpen wat deze betekenen.
Laten we beginnen met single-threading. Threading, als een concept, maakt gelijktijdige verwerking binnen een applicatie mogelijk. Node.js heeft deze mogelijkheid niet, althans niet in de traditionele zin. In plaats daarvan, om applicaties te schrijven die meerdere taken tegelijk uitvoeren, hebben we de asynchrone code en de event loop.
De event loop
Wat is de event loop?
De event loop is Node.js manier om langlopende processen op te splitsen in kleine brokjes. Het werkt als een hartslag: Elke paar milliseconden controleert Node.js een werkrij om nieuwe taken te starten. Als er werk is, worden deze op de aanroepstapel geplaatst en tot voltooiing uitgevoerd (we zullen het binnenkort hebben over uitvoeren tot voltooiing).
Door taken op te splitsen, kan Node.js multi-tasken, wat een vervanging is voor threading. Dat betekent dat terwijl een taak wacht, een andere kan beginnen. Dus, in plaats van threading, gebruiken we async code, gefaciliteerd door programmeerstijlen als callbacks, promises, en async/await. De meeste out-of-the-box Node API’s hebben zowel een synchrone als asynchrone methode van uitvoering.
Okay, dus misschien vraag je je af: wat heeft al dit techno-jargon met performance te maken?
Laat het me uitleggen…
Node.js performance en de event loop
Stel je voor dat je een Node.js applicatie bouwt met twee endpoints: een voor het uploaden van bestanden, en een die een gebruikersprofiel ophaalt. Het gebruikersprofiel API zal waarschijnlijk aanzienlijk vaker worden aangevraagd dan de bestandsupload, en als het niet snel genoeg reageert, zal het blokkeren elke pagina laden voor elke gebruiker-niet goed.
De gebruiker upload API wordt niet vaak gebruikt. Ook verwachten gebruikers dat het uploaden van taken tijd kost, maar ze zijn een stuk minder vergevingsgezind met laadtijden van pagina’s. Als we niet programmeren met de event loop in gedachten, terwijl het bestand aan het uploaden is, zou Node.js uiteindelijk alle systeembronnen kunnen opslokken en andere gebruikers kunnen blokkeren om je applicatie te gebruiken-uh-oh!
En dat is waarom je de single-threaded aard van Node.js moet begrijpen. Als we onze applicatie veranderen, moeten we dit gedrag overwegen. We willen voorkomen dat we langlopende taken synchroon uitvoeren, zoals het doen van netwerkverzoeken, het schrijven van bestanden, of het uitvoeren van een zware berekening.
Nu we weten over Node.js’s single-threaded aard, kunnen we het in ons voordeel gebruiken. Laten we stap voor stap bekijken hoe u een performancetest van uw Node.js-toepassing kunt opzetten, uitvoeren en analyseren om er zeker van te zijn dat u uw best doet om de Node.js-prestatiemogelijkheden te benutten.
Stap 1: Node.js-prestatietesttooling kiezen
Eerst zult u een tool willen kiezen waarmee u uw performancetests kunt uitvoeren. Er zijn veel tools, allemaal met verschillende voors en tegens voor Node.js performance tuning. Een belangrijk ding om te overwegen is dat ook al test je een Node.js applicatie als je gaat prestatietesten vanuit de buitenwereld over een netwerk, het niet uitmaakt of je prestatietest tooling is geschreven in Node.js.
Voor basis HTTP performance testing, hou ik van Artillery een rechttoe rechtaan performance testing tool geschreven in Node.js. Het is ook bijzonder goed in het uitvoeren van performance tests voor API-verzoeken. Artillery werkt door het schrijven van een configuratie bestand dat uw belasting profiel definieert. Je vertelt Artillery welke endpoints je wilt opvragen, in welk tempo, voor welke duur, etc.
Een basis testscript ziet er als volgt uit:
config: target: 'https://artillery.io' phases: - duration: 60 arrivalRate: 20 defaults: headers: x-my-service-auth: '987401838271002188298567'scenarios:- flow:- get:url: "/docs"
Hier, je vraagt de website van Artillery op voor een duur van 60 seconden met 20 nieuwe gebruikers die aankomen op de URL.
Dan, om de test uit te voeren, voert u eenvoudig uit:
artillery run your_config.yml
Artillery zal zoveel verzoeken aan uw toepassing doen als u het hebt opgedragen. Dit is handig voor het bouwen van performance test profielen die uw productie omgeving nabootsen. Wat bedoel ik met performance test profiel? Laten we dat nu behandelen.
Stap 2: Maak een Node.js performance test profiel
Een performance test profiel, zoals hierboven, is een definitie van hoe je performance test zal lopen. U zult willen nabootsen hoe uw productie-verkeer doet of wordt verwacht zich te gedragen, indien mogelijk om nauwkeurige Node.js performance tuning te doen. Bijvoorbeeld, als je een evenement website bouwt, verwacht je veel verkeer rond de tijd dat je tickets vrijgeeft, dus je zou een profiel willen bouwen dat dit gedrag nabootst. Je zou willen testen of je applicatie in staat is om te schalen met grote hoeveelheden verkeer in een korte tijd. Anderzijds, als u een e-commerce site runt, verwacht u misschien gelijkmatig verkeer. Hier zouden uw performance test profielen dit gedrag moeten weerspiegelen.
Gebruik maken van meerdere test profielen
Een leuk en interessant punt om op te merken is dat u verschillende test profielen kunt maken en deze op een overlappende manier kunt uitvoeren. Je zou bijvoorbeeld een profiel kunnen maken dat je basisniveau van verkeer nabootst – zeg 100 verzoeken per minuut – en dan nabootsen wat er zou kunnen gebeuren als je veel verkeer naar je site zou zien komen, bijvoorbeeld als je een aantal zoekmachine-advertenties zou plaatsen. Het testen van meerdere scenario’s is belangrijk voor grondige Node.js performance tuning.
Repliceren van grootschalige gedistribueerde systemen
Ik moet hier even een seconde nemen om iets op te merken: wanneer een applicatie een bepaalde grootte bereikt, verliest het nabootsen van belasting op deze manier zijn haalbaarheid. De verkeersvolumes die je hebt kunnen zo wild, onvoorspelbaar, of groot in volume zijn dat het moeilijk is om een realistische like-for-like manier te creëren om je applicatie te testen voor de release.
Maar wat als dit het geval is? Wat doen we dan? We testen in productie.
Je zou kunnen denken, “Woah, wacht even! Moeten we niet testen voor de release?”
Dat kan, maar als een systeem een bepaalde omvang krijgt, kan het zinvol zijn om andere strategieën voor prestatietests te gebruiken. Je kunt concepten als canary releasing gebruiken om je wijzigingen in productie te nemen en ze alleen met een bepaald percentage gebruikers te testen. Als je een prestatievermindering ziet, kun je dat verkeer terugschakelen naar je vorige implementatie. Dit proces moedigt echt experimenteren aan, en het beste deel is dat je test op je echte productie applicatie, dus geen zorgen over testresultaten die de productie niet nabootsen.
Zo ver hebben we besloten over onze tooling, en we hebben profielen gemaakt die onze productie nabootsen, zoals verkeer en workloads. Wat gaan we nu doen? We moeten ervoor zorgen dat we de gegevens hebben die we nodig hebben om onze applicatie te analyseren, en we doen dat door middel van Node.js performance monitoring en Application Performance Management (APM) tools. Wat is een APM? Lees verder, en ik zal het je laten weten!
Stap 3: Stel je observeerbaarheid/monitoring in
We willen niet alleen onze performancetest tegen onze applicatie uitvoeren en hopen en bidden. Als we dat doen, zullen we niet in staat zijn om te begrijpen hoe het presteert en of het doet wat we denken dat het zou moeten doen. Dus voordat we beginnen, moeten we onszelf vragen stellen als “Hoe ziet goed eruit voor mijn applicatie? Wat zijn mijn SLA’s en KPI’s? Welke statistieken zijn nodig om een prestatieprobleem effectief te debuggen?”
Als je app traag presteert, of anders dan verwacht, heb je gegevens nodig om te begrijpen waarom, zodat je het kunt verbeteren. Alle productieapplicaties die de moeite waard zijn, maken gebruik van een of andere vorm van observatie- en/of monitoringoplossing. Deze tools, vaak APM’s genoemd, stellen je in staat om kritische Node.js prestatiecijfers over je draaiende applicatie te bekijken.
Aan de slag met een APM
APM’s zijn er in verschillende soorten en maten, allemaal met verschillende functies, prijskaartjes, beveiligingsimplicaties, prestaties, noem maar op. Het loont de moeite om een beetje rond te shoppen om de beste tool voor uw behoeften te vinden. Het zijn deze tools die ons de inzichten en gegevens zullen geven die we nodig hebben wanneer we onze Node.js performance tests uitvoeren.
Dus, als we weten dat we onze applicatie moeten monitoren – wat moeten we dan precies monitoren?
Natuurlijk wil je zoveel mogelijk gegevens, maar hoezeer we ook van gegevens houden, we moeten realistisch zijn over waar te beginnen! De beste plaats om te beginnen is met de volgende drie gebieden:
- Geaggregeerde logs-Applicatielogs worden ofwel impliciet door sommige bibliotheken of expliciet door een ontwikkelaar gegenereerd om inzicht te krijgen in een applicatie. Met de meeste geaggregeerde logtools kun je gemakkelijk je gelogde gegevens doorzoeken en visualiseren. In ons geval konden we de prestaties van elk van onze API’s loggen en ze in een grafiek zetten.
- Inzichten in de infrastructuur-Jouw applicatie draait op een host van allerlei soorten, dus je zult waarschijnlijk alle gegevens willen zien. Als je in de cloud draait, geven de meeste providers je deze gegevens (zij het in een ruwe vorm) out of the box. De gegevens die u van deze tools krijgt, hebben betrekking op zaken als CPU- en geheugengebruik van uw host, verbindingsgegevens, enz.
- Applicatiemonitoring-Dit type tool bevindt zich meestal binnen uw applicatiecode en kan inzichtelijk maken hoe functies presteren/aangeroepen worden, welke fouten we gooien, enz.
Sommige APM-tools, zoals Retrace, hebben alle of de meeste van deze drie functies in één, terwijl andere meer gespecialiseerd kunnen zijn. Afhankelijk van uw vereisten wilt u misschien één tool die alles doet of een hele reeks tools voor verschillende doeleinden.
Tooling toegesneden op Node.js
Naast tools kunnen we ook andere Node.js-specifieke tools en profilers opnemen, zoals vlamdiagrammen, die kijken naar onze functie-uitvoering of gegevens extraheren over onze event-loop-uitvoering. Naarmate je meer vertrouwd raakt met Node.js performance testing, zullen je vereisten voor gegevens alleen maar groeien. Je zult willen blijven rondkijken, experimenteren en je tooling updaten om je applicatie echt te begrijpen.
Nu we onze tooling hebben opgezet, realistische profielen hebben voor onze performance, en onze applicatie performance begrijpen, zijn we bijna klaar om onze tests uit te voeren. Maar voordat we dat doen, is er nog één stap: het maken van testinfrastructuur.
Stap 4: Maak Node.js performance test infrastructuur
Je kunt performance tests vanaf je eigen machine uitvoeren als je dat wilt, maar er zijn problemen om dit te doen. Tot nu toe hebben we erg ons best gedaan – bijvoorbeeld met onze test profielen – om ervoor te zorgen dat onze performance tests repliceren. Een andere factor bij het repliceren van onze tests is ervoor te zorgen dat we ze altijd op dezelfde infrastructuur (lees: machine) uitvoeren.
Eén van de gemakkelijkste manieren om een consistente testinfrastructuur te bereiken is door gebruik te maken van cloud hosting. Kies een host/machine van waaruit u uw tests wilt starten en zorg ervoor dat elke keer dat u uw tests uitvoert, dit altijd vanaf dezelfde machine is, en bij voorkeur ook vanaf dezelfde locatie, om te voorkomen dat uw gegevens op basis van verzoeklatentie worden scheefgetrokken.
Het is een goed idee om deze infrastructuur te scripten, zodat u deze kunt maken en afbreken wanneer dat nodig is. Ze noemen dit idee “infrastructuur als code”. De meeste cloud providers ondersteunen dit, of je kunt een tool als Terraform gebruiken om je te helpen.
Phew! We hebben al veel gedaan, en we zijn nu bij de laatste stap: het uitvoeren van onze tests.
Stap 5: Voer uw tests uit!
De laatste stap is het daadwerkelijk uitvoeren van onze tests. Als we onze command line configuratie starten (zoals we deden in stap 1), zullen we requests zien naar onze Node.js applicatie. Met onze monitoring oplossing, kunnen we controleren hoe onze event loop presteert, of bepaalde requests langer duren dan andere, of verbindingen uittiming hebben, etc.
De kers op de taart voor je performance tests is om te overwegen om ze in je build en test pijplijn te zetten. Een manier om dit te doen is om je performance tests ’s nachts te draaien, zodat je ze elke ochtend kunt bekijken. Artillery biedt een mooie, eenvoudige manier om deze rapporten te maken, die je kunnen helpen om eventuele Node.js performance regressies te spotten.
Nu heb je bliksemsnelle Node.js
Dat is een wrap.
Vandaag hebben we de relevantie van de event loop voor de prestaties van je JavaScript-applicatie behandeld, hoe je je performance testing tooling kiest, hoe je consistente performance test profielen opzet met Artillery, welke monitoring je wilt opzetten om Node.js te diagnosticeren, en, ten slotte, hoe en wanneer u uw performance tests uitvoert om de meeste waarde voor u en uw team te krijgen.
Experimenteer met monitoring tools, zoals Retrace APM voor Node.js, breng kleine wijzigingen aan, zodat u de impact van wijzigingen kunt testen, en bekijk uw testrapporten regelmatig, zodat u regressies kunt spotten. Nu heb je alles wat je nodig hebt om gebruik te maken van Node.js performance mogelijkheden en een super performante applicatie te schrijven waar je gebruikers van houden!