Znamy Node.js z jego błyskawicznej wydajności. Jednak, jak w każdym języku, możesz napisać kod Node.js, który będzie działał gorzej dla użytkowników niż byś chciał. Aby temu zapobiec, potrzebujemy odpowiednich testów wydajnościowych. Dzisiaj zajmiemy się właśnie tym, dzięki dogłębnemu spojrzeniu na to, jak skonfigurować i uruchomić test wydajności oraz przeanalizować wyniki, aby móc tworzyć błyskawiczne aplikacje Node.js.
Najlepszym sposobem na zrozumienie, jak testować wydajność aplikacji, jest przejście przez przykład.
Możesz używać Node.js do wielu celów: pisania skryptów do wykonywania zadań, uruchamiania serwera WWW lub serwowania statycznych plików, takich jak strona internetowa. Dzisiaj przejdziemy przez etapy testowania HTTP web API Node.js. Ale jeśli budujesz coś innego w Node, nie martw się – wiele z zasad będzie podobnych.
- Unikalna natura wydajności Node.js
- Pętla zdarzeń
- Wydajność Node.js i pętla zdarzeń
- Krok 1: Wybór narzędzi do testowania wydajności Node.js
- Krok 2: Utwórz profil testu wydajności Node.js
- Wykorzystanie wielu profili testowych
- Replikowanie dużych systemów rozproszonych
- Krok 3: Ustaw obserwowalność/monitorowanie
- Powstanie i działanie z APM
- Narzędzia dostosowane do Node.js
- Krok 4: Stworzenie infrastruktury testów wydajności Node.js
- Krok 5: Uruchom swoje testy!
- Teraz masz błyskawicznie działający Node.js
Unikalna natura wydajności Node.js
Zanim zaczniemy, spójrzmy szybko na jedną z bardziej unikalnych cech wydajności Node.js. Będziemy musieli mieć wiedzę o tych cechach później, kiedy będziemy przeprowadzać nasze testy wydajności.
O czym mówię?
Ważnym aspektem dla aplikacji Node.js jest ich jednowątkowe, uruchamiane do końca zachowanie – ułatwione przez to, co jest znane jako pętla zdarzeń. Wiem, co sobie myślisz: to bardzo dużo. Więc rozbijmy to trochę, abyśmy zrozumieli, co one oznaczają.
Zacznijmy od pojedynczego wątkowania. Wątkowanie, jako koncepcja, pozwala na współbieżne przetwarzanie w ramach aplikacji. Node.js nie ma takiej możliwości, przynajmniej nie w tradycyjnym sensie. Zamiast tego, aby pisać aplikacje, które wykonują wiele zadań jednocześnie, mamy kod asynchroniczny i pętlę zdarzeń.
Pętla zdarzeń
Co to jest pętla zdarzeń?
Pętla zdarzeń jest sposobem Node.js na rozbicie długo trwających procesów na małe kawałki. Działa to jak bicie serca: Co kilka milisekund, Node.js sprawdzi kolejkę pracy, aby rozpocząć nowe zadania. Jeśli jest praca, przeniesie je na stos wywołań, a następnie uruchomi je do końca (wkrótce porozmawiamy o run-to-completion).
Dzięki rozbiciu zadań na mniejsze części, Node.js może działać wielozadaniowo, co jest substytutem gwintowania. Oznacza to, że podczas gdy jedno zadanie czeka, inne może się rozpocząć. Tak więc, zamiast gwintowania, używamy kodu async, ułatwionego przez style programowania takie jak callbacks, obietnice i async/await. Większość gotowych API Node ma zarówno synchroniczną, jak i asynchroniczną metodę wykonania.
Dobrze, więc może zastanawiasz się: co ten cały techno-żargon ma wspólnego z wydajnością?
Pozwól mi wyjaśnić…
Wydajność Node.js i pętla zdarzeń
Wyobraź sobie, że budujesz aplikację Node.js z dwoma punktami końcowymi: jednym do wysyłania plików i jednym, który pobiera profil użytkownika. API profilu użytkownika będzie prawdopodobnie żądane znacznie częściej niż przesłanie pliku, a jeśli nie odpowie wystarczająco szybko, zablokuje każde załadowanie strony dla każdego użytkownika – nie jest to dobre.
Przesłanie API użytkownika jest używane rzadko. Ponadto użytkownicy oczekują, że wgrywanie zadań zajmie trochę czasu, ale są o wiele mniej wyrozumiali w przypadku czasu ładowania strony. Jeśli nie będziemy programować z myślą o pętli zdarzeń, podczas gdy plik jest przesyłany, Node.js może skończyć hogging wszystkie zasoby systemowe i może zablokować innych użytkowników z korzystania z aplikacji-uh-oh!
I dlatego trzeba zrozumieć jednowątkową naturę Node.js. Gdy będziemy zmieniać naszą aplikację, musimy wziąć pod uwagę to zachowanie. Chcemy uniknąć wykonywania długo trwających zadań synchronicznie, takich jak wykonywanie żądań sieciowych, zapisywanie plików lub wykonywanie ciężkich obliczeń.
Teraz wiemy o jednowątkowej naturze Node.js, możemy wykorzystać ją na naszą korzyść. Prześledźmy krok po kroku, jak można skonfigurować, uruchomić i przeanalizować test wydajności aplikacji Node.js, aby upewnić się, że robisz wszystko, co w Twojej mocy, aby wykorzystać możliwości wydajności Node.js.
Krok 1: Wybór narzędzi do testowania wydajności Node.js
Po pierwsze, będziesz chciał wybrać narzędzie, które pozwoli Ci uruchomić testy wydajności. Istnieje wiele narzędzi, wszystkie z różnymi zaletami i wadami dla tuningu wydajności Node.js. Jedną z głównych rzeczy do rozważenia jest to, że nawet jeśli testujesz aplikację Node.js, jeśli zamierzasz testować wydajność ze świata zewnętrznego przez sieć, nie ma znaczenia, czy twoje narzędzia do testowania wydajności są napisane w Node.js.
Do podstawowego testowania wydajności HTTP, lubię Artillery proste narzędzie do testowania wydajności napisane w Node.js. Jest ono również szczególnie dobre do przeprowadzania testów wydajnościowych dla żądań API. Artillery działa poprzez napisanie pliku konfiguracyjnego, który definiuje profil obciążenia. Mówisz Artillery, które punkty końcowe chcesz zażądać, w jakim tempie, przez jaki czas, itp.
Podstawowy skrypt testowy wygląda tak:
config: target: 'https://artillery.io' phases: - duration: 60 arrivalRate: 20 defaults: headers: x-my-service-auth: '987401838271002188298567'scenarios:- flow:- get:url: "/docs"
Tutaj żądasz strony internetowej Artillery przez 60 sekund z 20 nowymi użytkownikami przybywającymi na adres URL.
Następnie, aby przeprowadzić test, po prostu wykonaj:
artillery run your_config.yml
Artillery wykona tyle żądań do Twojej aplikacji, ile jej poleciłeś. Jest to przydatne do budowania profili testów wydajnościowych, które naśladują środowisko produkcyjne. Co mam na myśli mówiąc o profilu testu wydajności? Zajmijmy się tym teraz.
Krok 2: Utwórz profil testu wydajności Node.js
Profil testu wydajności, jak powyżej, jest definicją tego, jak Twój test wydajności będzie działał. Będziesz chciał naśladować to, jak Twój ruch produkcyjny zachowuje się lub powinien się zachowywać, jeśli to możliwe, aby wykonać dokładne strojenie wydajności Node.js. Na przykład, jeśli budujesz stronę internetową z wydarzeniami, spodziewasz się dużego ruchu w czasie wydawania biletów, więc będziesz chciał zbudować profil, który naśladuje to zachowanie. Chciałbyś przetestować zdolność aplikacji do skalowania z dużym obciążeniem w krótkim czasie. Alternatywnie, jeśli prowadzisz witrynę e-commerce, możesz spodziewać się równomiernego ruchu. Tutaj, twoje profile testów wydajności powinny odzwierciedlać to zachowanie.
Wykorzystanie wielu profili testowych
Zabawnym i interesującym punktem do odnotowania jest to, że możesz tworzyć różne profile testowe i uruchamiać je w nakładający się sposób. Na przykład, można utworzyć profil, który naśladuje podstawowy poziom ruchu – powiedzmy, 100 żądań na minutę – a następnie naśladować to, co mogłoby się stać, gdybyś zobaczył dużo ruchu na swojej stronie, powiedzmy, jeśli umieścić kilka reklam w wyszukiwarkach. Testowanie wielu scenariuszy jest ważne dla dokładnego dostrajania wydajności Node.js.
Replikowanie dużych systemów rozproszonych
Muszę poświęcić sekundę, aby coś zauważyć: Kiedy aplikacja osiąga pewien rozmiar, naśladowanie obciążenia w ten sposób traci wykonalność. Natężenie ruchu, które możesz mieć, może być tak dzikie, nieprzewidywalne lub duże, że trudno jest stworzyć realistyczny, podobny sposób testowania aplikacji przed jej wydaniem.
Ale co jeśli tak jest? Co robimy? Testujemy w produkcji.
Możesz pomyśleć, „Woah, poczekaj! Czy nie powinniśmy testować przed wydaniem?”
Możesz, ale kiedy system osiągnie pewien rozmiar, może mieć sens wykorzystanie innych strategii testowania wydajności. Możesz wykorzystać koncepcje takie jak uwolnienie kanarka, aby wypuścić swoje zmiany na produkcję i przetestować je tylko z pewnym procentem użytkowników. Jeśli zauważysz spadek wydajności, możesz zamienić ten ruch z powrotem na poprzednią implementację. Ten proces naprawdę zachęca do eksperymentowania, a najlepszą częścią jest to, że testujesz na prawdziwej aplikacji produkcyjnej, więc nie ma obaw o to, że wyniki testów nie naśladują produkcji.
Do tej pory zdecydowaliśmy się na nasze narzędzia i stworzyliśmy profile, które odtwarzają naszą produkcję, jak ruch i obciążenia. Co robimy dalej? Musimy upewnić się, że mamy dane, których potrzebujemy do analizy naszej aplikacji, a robimy to poprzez monitoring wydajności Node.js i narzędzia do zarządzania wydajnością aplikacji (APM). Co to jest APM? Czytaj dalej, a ja ci powiem!
Krok 3: Ustaw obserwowalność/monitorowanie
Nie chcemy po prostu uruchomić naszego testu wydajności przeciwko naszej aplikacji i mieć nadzieję i modlić się. Jeśli to zrobimy, nie będziemy w stanie zrozumieć jak działa i czy robi to, co myślimy, że powinna. Dlatego zanim zaczniemy, powinniśmy zadać sobie pytania w stylu: „Jak wygląda dobra wydajność dla mojej aplikacji? Jakie są moje SLA i KPI? Jakie metryki są potrzebne, aby skutecznie rozwiązać problem z wydajnością?”
Jeśli Twoja aplikacja działa wolno lub inaczej niż się spodziewałeś, będziesz potrzebował danych, aby zrozumieć dlaczego tak się dzieje, abyś mógł to poprawić. Wszystkie aplikacje produkcyjne warte swojej soli używają jakiejś formy obserwowalności i/lub rozwiązania monitorującego. Narzędzia te, często nazywane APM, pozwalają na przeglądanie krytycznych metryk wydajności Node.js na temat działającej aplikacji.
Powstanie i działanie z APM
APM są w różnych kształtach i rozmiarach, wszystkie z różnymi funkcjami, tagami cenowymi, implikacjami bezpieczeństwa, wydajnością, możesz to nazwać. Opłaca się trochę poszukać, aby znaleźć najlepsze narzędzie dla swoich potrzeb. To właśnie te narzędzia dadzą nam wgląd i dane, których potrzebujemy, gdy przeprowadzamy nasze testy wydajności Node.js.
Więc, jeśli wiemy, że powinniśmy monitorować naszą aplikację – co dokładnie powinniśmy monitorować?
Naprawdę, chcesz mieć jak najwięcej danych, ale tak bardzo jak kochamy dane; musimy być realistami co do tego, od czego zacząć! Najlepszym miejscem do rozpoczęcia są trzy następujące obszary:
- Zagregowane logi – Logi aplikacji są emitowane albo niejawnie przez niektóre biblioteki, albo jawnie przez programistę w celu uzyskania wglądu w aplikację. Większość narzędzi do agregacji logów pozwala na łatwe wyszukiwanie i wizualizację logowanych danych. W naszym przypadku, możemy wylogować wydajność każdego z naszych API i umieścić je na wykresie.
- Wgląd w infrastrukturę – Twoja aplikacja będzie działać na różnych hostach, więc prawdopodobnie będziesz chciał zobaczyć wszystkie dane. Jeśli pracujesz w chmurze, większość dostawców udostępnia te dane (choć w prymitywnej formie) po wyjęciu z pudełka. Dane, które uzyskasz z tych narzędzi będą obejmować takie rzeczy jak wykorzystanie CPU i pamięci hosta, dane o połączeniach, itp.
- Monitorowanie aplikacji – Ten typ narzędzia zazwyczaj siedzi w kodzie aplikacji i może wyciągnąć wnioski na temat tego, jak funkcje są wykonywane/wywoływane, jakie błędy rzucamy, itp.
Niektóre narzędzia APM, takie jak Retrace, mają wszystkie lub większość z tych trzech funkcji w jednym, podczas gdy inne mogą być bardziej wyspecjalizowane. W zależności od twoich wymagań, możesz chcieć jednego narzędzia, które robi wszystko lub całą gamę narzędzi do różnych celów.
Narzędzia dostosowane do Node.js
Na wierzchu narzędzi, możemy również zawrzeć inne narzędzia specyficzne dla Node.js i profilery, takie jak wykresy płomieni, które patrzą na wykonanie naszych funkcji lub wydobywają dane o wykonaniu naszej pętli zdarzeń. W miarę jak będziesz coraz lepiej zorientowany w testowaniu wydajności Node.js, twoje wymagania co do danych będą tylko rosły. Będziesz chciał ciągle kupować, eksperymentować i aktualizować swoje narzędzia, aby naprawdę zrozumieć swoją aplikację.
Po skonfigurowaniu naszych narzędzi, uzyskaniu realistycznych profili dla naszej wydajności i zrozumieniu wydajności naszej aplikacji, jesteśmy prawie gotowi do uruchomienia naszych testów. Ale zanim to zrobimy, jest jeszcze jeden krok: stworzenie infrastruktury testowej.
Krok 4: Stworzenie infrastruktury testów wydajności Node.js
Możesz uruchomić testy wydajności z własnej maszyny, jeśli chcesz, ale są problemy z robieniem tego. Do tej pory bardzo się staraliśmy, na przykład za pomocą naszych profili testowych, aby zapewnić replikację naszych testów wydajnościowych. Innym czynnikiem w replikowaniu naszych testów jest zapewnienie, że zawsze uruchamiamy je na tej samej infrastrukturze (czytaj: maszynie).
Jednym z najprostszych sposobów na osiągnięcie spójnej infrastruktury testowej jest wykorzystanie hostingu w chmurze. Wybierz hosta/maszynę, z której chcesz uruchamiać swoje testy i upewnij się, że za każdym razem, gdy uruchamiasz swoje testy, to zawsze z tej samej maszyny – a najlepiej z tej samej lokalizacji, aby uniknąć zniekształcenia danych w oparciu o opóźnienie żądania.
Dobrym pomysłem jest oskryptowanie tej infrastruktury, abyś mógł ją tworzyć i niszczyć w razie potrzeby. Nazywają ten pomysł „infrastrukturą jako kodem”. Większość dostawców chmur obsługuje ją natywnie lub możesz użyć narzędzia takiego jak Terraform, aby Ci pomóc.
Phew! Do tej pory pokonaliśmy sporo terenu i jesteśmy na ostatnim etapie: uruchomienie naszych testów.
Krok 5: Uruchom swoje testy!
Ostatnim krokiem jest faktyczne uruchomienie naszych testów. Jeśli uruchomimy naszą konfigurację wiersza poleceń (tak jak zrobiliśmy to w kroku 1), zobaczymy żądania do naszej aplikacji Node.js. Dzięki naszemu rozwiązaniu monitorującemu, możemy sprawdzić jak działa nasza pętla zdarzeń, czy niektóre żądania trwają dłużej niż inne, czy połączenia się kończą, itp.
Lukrem na torcie dla twoich testów wydajności jest rozważenie umieszczenia ich w twoim potoku budowania i testowania. Jednym ze sposobów, aby to zrobić jest uruchomienie testów wydajnościowych w nocy, tak abyś mógł je przejrzeć każdego ranka. Artillery zapewnia miły, prosty sposób tworzenia takich raportów, które mogą pomóc w wykryciu wszelkich regresji wydajności Node.js.
Teraz masz błyskawicznie działający Node.js
To wszystko.
Dzisiaj omówiliśmy znaczenie pętli zdarzeń dla wydajności Twojej aplikacji JavaScript, jak wybrać narzędzia do testowania wydajności, jak skonfigurować spójne profile testów wydajności z Artillery, jaki monitoring będziesz chciał skonfigurować, aby zdiagnozować problemy z wydajnością Node.js i w końcu, jak i kiedy przeprowadzać testy wydajności, aby uzyskać największą wartość dla Ciebie i Twojego zespołu.
Eksperymentuj z narzędziami monitorującymi, takimi jak Retrace APM dla Node.js, wprowadzaj małe zmiany, abyś mógł przetestować ich wpływ i często przeglądaj raporty z testów, abyś mógł dostrzec regresje. Teraz masz już wszystko, czego potrzebujesz, aby wykorzystać możliwości wydajnościowe Node.js i napisać superwydajną aplikację, którą pokochają Twoi użytkownicy!