Skip to content

JMeter – testujemy wydajność

przez Łukasz Picur - Luty 17th, 2011

Istnieje bardzo wiele rodzajów testów. Można dyskutować nad tym jak istotne są poszczególne ich typy, ale trudno nie zaliczyć testów wydajnościowych do grupy o wyższym priorytecie. Nabierają one jeszcze większego znaczenia w przypadku aplikacji internetowych, gdzie z kilku instancji korzystają rzesze użytkowników. Jednym z popularniejszych narzędzi służących do przeprowadzania tego rodzaju testów jest JMeter. Program ten napisany jest w 100% w Javie, dzięki czemu jesteśmy w stanie uruchomić go praktycznie na każdym systemie operacyjnym. Udostępnia także graficzny interfejs, który upraszcza tworzenie scenariuszy testowych. Celem tego artykułu jest przedstawienie głównych elementów budulcowych wspomnianego scenariusza, oraz demonstracja ich użycia.

Pierwszym krokiem jest pobranie najnowszej wersji JMeter’a – można to zrobić na tej stronie. Jeśli ktoś potrzebuje jednej z wersji archiwalnych, są one dostępne pod tym samym adresem. Aby uruchomić program, należy otworzyć katalog bin znajdujący się w rozpakowanym archiwum. Znajdziemy tam gotowe pliki dla najpopularniejszych systemów operacyjnych, np. jmeter.bat, czy jmeter.sh. Możemy z nich skorzystać, lub użyć bardziej uniwersalnej metody, czyli uruchomić plik ApacheJmeter.jar. Wystarczy wykonać jedną, prostą komendę

java -jar ApacheJMeter.jar

Niezależnie od tego, którą drogę wybraliśmy, naszym oczom powinno pokazać się okno JMeter’a wyglądające mniej więcej tak:

Okno główneJak widać, jest ono podzielone na dwie części. Drzewko po lewej służy do tworzenia scenariusza poprzez dodawanie gotowych komponentów udostępnianych przez aplikację. Panel po prawej umożliwia edycję właściwości elementów drzewa. Zanim jednak zaczniemy tworzyć własny test, warto dowiedzieć się więcej na temat wspomnianych komponentów, które posłużą nam jako elementy budulcowe.

Z czego składa się test?

Podstawowym elementem naszego testu jest tzw. ThreadGroup. Jak sama nazwa wskazuje, symuluje on grupę użytkowników wchodzących w interakcję z testowaną aplikacją. Każdy taki „użytkownik” działa niezależnie od innych, w swoim osobnym wątku. ThreadGroup pozwala nam na skonfigurowanie trzech podstawowych parametrów testu, a mianowicie:

  • Ilość wątków/użytkowników.
  • Czas rozruchu (tzw. ramp-up period) – czas, po którym aktywne będą wszystkie wątki. Jeśli ich ilość ustaliliśmy na 10, a ramp-up period na 20 sekund, to co 2 sekundy dodawany będzie kolejny wątek wykonujący nasz scenariusz testowy.
  • Ilość powtórzeń dla każdego wątku – określa ile razy każdy z wątków wykona scenariusz testowy.

Od wersji 1.9 dostępny jest także scheduler, który pozwala określić dokładne daty rozpoczęcia i zakończenia testów, lub opóźnienie startu i czas trwania w sekundach.

Do elementu ThreadGroup dodajemy kontrolery, które można uznać za siłę napędową testu. Wyróżniamy ich dwa rodzaje:

  • Samplery – służą do wysyłania żądań. Nas interesują głównie żądania HTTP, ale istnieją też samplery obsługujące protokoły SOAP, FTP, JDBC, LDAP i inne. Samplery możemy modyfikować poprzez zmianę ich właściwości, lub dodanie do drzewa elementów Configuration Element. Umieszczone w naszym teście Listenery pozwolą monitorować żądania poszczególnych samplerów i otrzymane od serwera odpowiedzi.Możemy również przeprowadzić prostą walidację odpowiedzi serwera przy pomocy elementów z rodziny Assertion.
  • Logic Controllery – umożliwiają zmianę logiki odpowiedzialnej za uruchamianie poszczególnych samplerów. Daje to możliwość wywoływania samplerów w pętli, wybrania losowego samplera z zadanej grupy itd.

Aby dokładniej zasymulować człowieka używającego naszej aplikacji, możemy wprowadzić do naszego testu przerwy czasowe. Służą do tego elementy z kategorii Timers. Ostatnimi grupami elementów, o których należy wiedzieć, są Pre-Procesory i Post-Procesory. Te pierwsze pozwalają na wykonanie jakiejś akcji tuż przed wysłaniem żądania przez sampler, i zazwyczaj są używane do zmodyfikowania elementów tego żądania. Elementy z drugiej grupy dają możliwość wykonania pewnej akcji po wysłaniu żądania. Ich najczęstszym zastosowaniem jest wyodrębnienie fragmentu odpowiedzi serwera i zapisanie go pod pewną nazwą.

Kilka słów o zasięgu i kolejności

Przy konstruowaniu testu z wykorzystaniem JMeter’a warto pamiętać, że dla elementów, z których przyjdzie nam korzystać, liczyć może się ich kolejność (ordered), lub miejsce w ogólnej hierarchii (hierarchical). Do pierwszej grupy należą kontrolery, które wykonują się w takim porządku, w jakim zostały dodane do drzewa. Do komponentów hierarchicznych możemy zaliczyć m.in. asercje, timery, czy elementy konfiguracyjne. Mają one wpływ na wszystkie elementy drzewa  z tego samego i niższych poziomów. Jeśli więc dodamy timer bezpośrednio do root’a drzewa (Test Plan), będzie on miał wpływ na wszystkie samplery w tym teście. Lepiej zobrazuje to przykład, który przeanalizujemy w następnej kolejności.

Testujemy!

Nasz przykładowy test ma na celu zasymulowanie użytkownika, który wchodzi na stronę javablog.eu. Znajduje się na niej pierwszy raz, dlatego postanawia kliknąć w link „Informacje”. Tam widzi odnośnik do witryny TIOBE – odwiedza ją, ale szybko wraca do naszego bloga. Jako, że interesują go zagadnienia związane ze Spring Security, decyduje się na wyszukanie wszystkich postów o tej tematyce. Następnie, w zależności od upodobań, odwiedza pierwszą lub drugą podstronę spośród otrzymanych rezultatów. Jest to scenariusz bardzo prosty, jednak pozwoli zademonstrować najważniejsze aspekty konstruowania testu. Na początek spójrzmy, jak wygląda drzewo elementów dla takiego przypadku.

THREAD GROUP

Zaczynając od „góry”, do korzenia drzewa dodanych jest pięć elementów. Pierwszym jest grupa wątków (ThreadGroup), której właściwości są wyświetlone na panelu po prawej stronie. Aby nie wydłużać działania testu, który służyć ma wyłącznie celom demonstracyjnym, wszystkie wartości ustawione są na 1. Mamy więc jednego użytkownika, który raz wykona cały scenariusz testowy. Kolejne 3 komponenty są to elementy konfiguracyjne (Configuration Elements). Z faktu, że dodane zostały bezpośrednio do korzenia drzewa wynika, iż w ich zasięgu są wszystkie samplery naszego testu.

REQUEST DEFAULTS (HTTP Request Defaults) określa domyślne parametry żądania HTTP. Daje to możliwość globalnego ustawienia hosta, portu, kodowania znaków itp.

REQUEST DEFAULTS

COOKIE MANAGER (HTTP Cookie Manager) wzbogaca nasz test o obsługę ciasteczek. Jest to szczególnie ważne w przypadku testów, których elementem jest uwierzytelnianie. GLOBAL VARIABLES (User Defined Variables), jak sama nazwa sugeruje, pozwala na zdefiniowanie zmiennych o pewnych wartościach w celu późniejszego użycia.

GLOBAL VARIABLES

Na końcu znajduje się jeden z dostępnych Listenerów (View Results Tree), który umożliwia podglądnięcie wysyłanych przez samplery żądań i otrzymywanych odpowiedzi. Warto także pamiętać o tym, że każdy Listener posiada możliwość eksportu zebranych danych do pliku.

LISTENER
Przechodząc wgłąb drzewka widać, że do grupy wątków dodany jest Timer oraz kilka Samplerów, w tym dwa wewnątrz Logic Controllera. Dodatkowo część samplerów posiada Post-Procesory. Wspomniany timer, z uwagi na swoje położenie, wpływa na wszystkie samplery wewnątrz grupy wątków. Spowalnia on ich wykonywanie poprzez wprowadzenie losowego opóźnienia przed wysłaniem żądania.

TIMER

Pierwszy sampler wysyła żądanie otrzymania strony domowej javablog.eu. Jedyny atrybut, którego wartość jest zmieniona, to path.

MAIN PAGEKolejny sampler odpowiada za pobranie strony z informacjami o blogu. W tym przypadku zmieniany był także tylko URL. Co jednak ciekawe, dodany jest do niego Post-Procesor, którego funkcją jest wyodrębnienie adresu witryny TIOBE i zapisanie go pod określoną nazwa. Warte wyjaśnienia są właściwości tego elementu:

  • Reference Name – nazwa zmiennej, w której będzie przechowywana wyodrębniona wartość.
  • Regular Expression – wyrażenie regularne, do którego dopasowań będziemy szukać.
  • Template – ostateczna wartość, jaka zostanie zapisana w zmiennej. $1$ oznacza pierwszą grupę wyrażenia regularnego.
  • Match No. – w przypadku wielu dopasowań parametr ten określa, które z nich będzie brane pod uwagę.
  • Default Value – domyślna wartość, używana w przypadku braku dopasowania.

TIOBE URLTrzeci z kolei sampler korzysta z adresu zapisanego w zmiennej o nazwie tiobeURL i pobiera zawartość tejże strony. Warto w tym miejscu zwrócić uwagę na sposób odnoszenia się do zmiennej w JMeterze. Robimy to umieszczając jej nazwę w nawiasach klamrowych poprzedzonych znakiem dolara: ${var}.

TIOBEW następnej kolejności symulujemy wyszukiwanie treści na stronie. Wymaga to od nas dodania do żądania parametru określającego frazę, po której chcemy szukać. Można to łatwo zrobić w oknie właściwości samplera. Przykład udowadnia także, iż zmiennych możemy używać również do nadawania wartości parametrom żądań. W tym przypadku wykorzystywana jest zmienna globalna zdefiniowana wcześniej.

SEARCH

Z otrzymanej listy wyników wyodrębniamy adresy pierwszego i drugiego elementu, oraz zapisujemy je pod określonymi nazwami. Dokonujemy tego, tak jak poprzednio, przy użyciu Post-Procesorów dodanych do samplera.

RESULT IRESULT IIOstatnią czynnością, którą musimy wykonać, jest wczytanie strony odpowiadającej pierwszemu lub drugiemu rezultatowi wyszukiwania. Użyjemy w tym miejscu Random Controllera. Jego działanie jest bardzo proste – wybiera on losowo jeden z dodanych do niego samplerów, i uruchamia go. W naszym przypadku wybór ogranicza się do dwóch elementów, dlatego też Random Controller będzie miał dwójkę „dzieci”.

RESULT I PAGERESULT II PAGE

W tym momencie zakończyliśmy tworzenie przykładowego scenariusza testowego. Nie pozostało nic innego jak wyświetlić właściwości dodanego wcześniej Listenera, uruchomić test (Ctrl + R) i podziwiać jak wysyłane są kolejne żądania. W przypadku większej ilości wątków i iteracji warto dodać Listenery wyświetlające ogólne statystyki – np. Summary Report.

SUMMARY

Plik zawierający przeanalizowany przez nas test można pobrać tutaj. Zachęcam oczywiście do samodzielnego eksperymentowania i testowania innych niż opisane komponentów.

JMeter a duża ilość wątków/użytkowników

Z moich doświadczeń wynika, że ilość wątków większa od 100 powoduje bardzo wyraźny spadek wydajności programu. Oczywiście duże znaczenie ma też stopień skomplikowania testu oraz wydajność używanej przez nas maszyny, ale bardzo prawdopodobne jest, że komputer nie wytrzyma dużej ilości symulowanych użytkowników. W takiej sytuacji proces testowania należy rozdzielić pomiędzy kilka hostów. Jest to o tyle proste, że jedna instancja aplikacji może kontrolować oraz zbierać dane z dowolnej liczby instancji działających zdalnie. Zagadnienie to jest bardzo dobrze opisane tutaj, a dodatkowo udostępniony jest tutorial w formacie PDF poświęcony w całości testowaniu rozproszonemu z wykorzystaniem JMetera.

Co dalej?

Osobom, które zainteresowały się testami wydajnościowymi i JMeterem, mogę śmiało polecić manual znajdujący się na oficjalnej stronie projektu. Sekcje opisujące cały proces tworzenia scenariusza są może odrobinę ubogie w detale, ale za to prawdziwą skarbnicę wiedzy stanowią wszelkiego rodzaju spisy, np. komponentów czy funkcji. Artykułów opisujących bardziej skomplikowane zagadnienia związane z JMeterem nie zabraknie też na javablog.eu.

Kategoria → Java, Web

6 komentarzy
  1. W artykule (bardzo i ciekawym skądinąd) brakuje mi wzmianki o znakomitym projekcie jmeter-plugins. Bez tego zbioru dodatków JMeter wydaje się wyjątkowo ograniczonym i dość topornym narzędziem w porównaniu z ofertą produktów komercyjną.

    • Dzięki za informację! Szczerze mówiąc nie miałem z tym pluginem styczności, ale wygląda bardzo ciekawie. Przy najbliższej okazji postaram się bliżej się z nim zapoznać i zamieścić jakiś tekst na łamach serwisu.

  2. dobry artykuł. kolejna rzecz, którą można by do niego dodać to info o komunikacji serwer klient przy zdalnym wywołaniu testów. domyślne ustawienia gwarantują nam zbieranie próbek w czasie rzeczywistym co potrafi wygenerować potworne ilości ruchu w sieci.
    w pliku jmeter.properties jest zmienna mode, którą warto pomanewrować (pod nią są jeszcze dwie zmienne które również mają wpływ na częstość zbierania próbek a stąd i na ilość generowanego ruchu w sieci).

    • Dzięki za komentarz i uwagi. Rozproszone testy wydajnościowe zostawiłem sobie na osobny artykuł, który mam nadzieję już niedługo powstanie. Nie zabraknie też zmiennej mode, o której wspomniałeś :)

  3. Dzmitry Kashlach permalink

    Hi,
    Some words about results reporting in Jmeter. For now there are two main option in this branch:
    – google-plugins(by Andrey Pohilko);
    jmeter plugin from blazemeter, which allows to upload result to cloud and observe them, using comprehensive graphs.

Trackbacks & Pingbacks

  1. Testy wydajnościowe aplikacji internetowych « Krzysztof Bielski

Zostaw komentarz

Info: XHTML jest dozwolony. Twój adres email nigdy nie będzie opublikowany.

Obserwuj komentarze poprzez RSS