Odpowiedzią działu IT na zwiększone zapotrzebowanie ze strony naszego biznesu na aplikacje internetowe była optymalizacja kosztów procesu produkcyjnego. Na etapie testowania naszych rozwiązań zdecydowaliśmy się na kierunek automatyzacji testów. Narzędziem, które m. in. zaczęliśmy intensywnie wykorzystywać był JMeter. Głównym przeznaczeniem tej aplikacji jest przeprowadzanie testów funkcjonalnych różnorodnych systemów, symulacja dużego obciążenia a także analiza wydajności, w tym graficzna. Jest to nieocenione narzędzie tak dla zespołów developerskich, jak i dla zespołu Quality Assurance.Elastyczność tego narzędzia pozwala nam na stałe jego dopasowywanie do zmieniającej się architektury Onet.pl, dzięki czemu unikamy kosztownych migracji z jednego narzędzia na inne. Niewątpliwą zaletą tego produktu jest także licencja Open Source.

Cechy

Lista cech JMeter’a jest długa. Ciężko mi tutaj je szeregować względem jakiegoś wybranego kryterium. Przede wszystkim JMeter został zrealizowany w technologii Java. Tak, wiem, są zwolennicy jak i przeciwnicy tej technologii, ale nie chcę tutaj rozwijać tego tematu. W naszym przypadku po prostu wykorzystujemy przenośność aplikacji realizowanych w Java w oparciu o JVM. Nie jest problemem dla naszych developerów pracujących czy to pod kontrolą systemu operacyjnego MSWindows, czy też Linux, użycie w każdej chwili Jmeter’a i to bez konieczności jego instalacji. Cechą pochodną do tutaj wymienionej, jest możliwość dostosowywania Jmeter’a do naszych indywidualnych potrzeb dzięki budowie modułowej. Zaimplementowana przez nas obsługa specyficznych dla naszej architektury protokołów komunikacyjnych,pozwala nam na szybkie i łatwe użycie JMeter’a do testowania dowolnego systemu przez nas zrealizowanego, i to na dowolnej warstwie architektury wielowarstwowej.

Z cech stricte technicznych mógłbym wymienić pełną wielowątkowość generatora ruchu testowego, pełny zapis wyników uzyskanych w trakcie realizacji testów, bardzo dobry projekt GUI, czy też możliwość użycia języka JavaScript.

Budowa

Filozofia pracy z JMeter’em oparta jest o element logiczny o nazwie Thread Group. Jest to grupa wątków, która stanowi podstawowy element każdego scenariusza testowego. Wszystkie pozostałe elementy muszą być dowiązane do tego właśnie elementu. Pozwala on skonfigurować liczbę wątków (użytkowników), sposób ich uruchamiania, liczbę powtórzeń scenariusza testowego.

Poniżej przykładowy scenariusz testowy.

Pozostałe moduły JMeter’a można pogrupować według ich przeznaczenia. I tak, można tutaj wymienić takie elementy, jak:

  • Samplers
    • Odpowiadają za wysłanie żądania do serwera
    • Obsługiwane protokoły: FTP, HTTP, JDBC, Java object request, LDAP, SOAP/XML-RPC, WebService (SOAP)
  • Logical Controllers
    • Decydują kiedy wysłać żądanie
    • Mogą zawierać elementy takie jak: Samplers, Configuration, inne Logical Controllers
    • Przykładowe moduły: Simple Controller, ForEach Controller, If Controller
  • Listeners
    • Zapewniają dostęp do wyników testów
    • Przykładowe moduły: Graph Result (wykresy czasu odpowiedzi), View Result Tree
  • Timers
    • Wprowadzają opóźnienia pomiędzy kolejnymi żądaniami
  • Assertions
    • Zapewniają weryfikację odpowiedzi
    • Przykład: czy odpowiedź element HTTP Request zawiera ciąg znaków “</HTML>”
  • Configuration Elements
    • pracują wspólnie z elementami Samplers,
    • nie wysyłają żądań, ale mogą je modyfikować
    • przykład: HTTP Cookie Manager, HTTP Request Defaults
  • Pre i Post-Processors Elements
    • używane do modyfikacji żądania przed jego wysłaniem lub modyfikacji odpowiedzi

Dane testowe

No dobrze. Używamy fajnego narzędzia, ale skąd wziąć dane testowe? Skąd developer realizujący testy w fazie produkcji, czy też inżynier jakości otrzymujący gotowy produkt do przetestowania w fazie akceptacji, może je wziąć? Odpowiedź jest prosta, choć nie zawsze jesteśmy w stanie ją osiągnąć – z ruchu produkcyjnego J.  Jmeter jest wyposażony w moduł Access Log Sampler, którego głównym zadaniem jest generowanie ruchu na podstawie „access” logów serwerów produkcyjnych.Rozwiązanie bardzo wygodne, ale czasem wymagające konfiguracji serwera produkcyjnego. Pamiętamy też, iż mając na myśli „jakość” równocześnie mamy na myśli „bezpieczeństwo”. Stąd uważnie dobieramy to rozwiązanie do potrzeb, aby nie narazić się na konflikty z Polityką Bezpieczeństwa,takie jak np. zapisywanie haseł czy też danych osobowych.

Alternatywnym rozwiązaniem znacznie przyśpieszającym proces przygotowania danych testowych jest użycie Jmeter’a jako Proxy.Funkcjonalność ta jest integralną częścią Jmeter’a i do jej podstawowych zadań należy przechwytywanie ruchu z przeglądarki i zapisywanie żądań http w postaci gotowego scenariusza testowego.

Meteory

Tematem, z którym mocno zetknęliśmy się podczas pierwszych naszych testów, była kwestia wydajności środowiska testującego. Piszę„testującego”, jako środowiska generującego ruch testowy i przetwarzającego wyniki, w odróżnieniu od środowiska „testowanego”,którego wydajność badamy. Po prostu okazało się, że wydajność serwera testującego jest mniejsza niż serwera testowanego. Przykładowo pojedynczy węzeł JMetera na CPU 1,4-3GHz był w stanie obsłużyć ok. 200wątków w zależności od typu testu, a dla technologii WebServices, która intensywnie korzysta z przetwarzania XML, wydajność była dużo mniejsza.Jednak twórcy narzędzia JMeter przewidzieli możliwość łączenia pojedynczych węzłów JMeter w jeden, duży, rozproszony system testujący pracujący pod wspólnym „dowództwem” wybranego węzła. Dzięki temu rozwiązaniu można uzyskać duży potencjał wydajności środowiska testującego, który jest zarządzany z pojedynczego węzła.
Meteory – wydajność
Aby zdjąć z osób przygotowujących testy konieczność ręcznej konfiguracji takiego środowiska rozproszonego oraz kwestię zapewnienia odpowiednich zasobów obliczeniowych w węzłach sieci, podjęliśmy decyzję o wydzieleniu z naszej architektury sprzętowej kilku dedykowanych serwerów pracujących pod kontrolą Linuxa. Rozwiązanie to otrzymało nazwę „Meteorów” – zapewne któremuś z nas węzły sieci skojarzyły się z meteorami a ruch przez nie generowany ze śladami po nich na nocnym niebie. Czasem nawet humorystycznie Kierownik Projektu zapyta, czy wyprodukowane w jego zespole projektowym rozwiązanie oprze się rojowi meteorów  :).

Nie obyło się oczywiście bez innego tematu mocno wtedy rozwijanego w Onecie, czyli wirtualizacji. Nasi administratorzy nie omieszkali nas wyposażyć w choć jeden wirtualny kontener. Można tutaj dyskutować nad przydatnością tego rozwiązania, biorąc pod uwagę sposób wykorzystania zasobów systemowych przez JMeter’a.

Wracając do narzędzia – dobrą praktyką, podczas intensywnych testów wydajnościowych, jest użycie prostego modułu rejestrującego wyniki testu, np. modułu Simple Data Writer, oraz rezygnacja z graficznej analizy „online”. Uzyskana przez nas maksymalna wydajność podczas testów jednego z takich projektów wynosiła 12 tys. zapytań na sekundę.Inną zaletą takiego rozwiązania, która wkrótce po oddaniu do użytku Meteorów uwidoczniła nam się wszystkim, była kwestia powtarzalności testów poprzez zastosowanie jednej, spójnej struktury katalogów zawierających scenariusze testowe, dane testowe oraz zebrane w trakcie pomiarów wyniki. Znacznie skrócił się dzięki temu czas potrzebny na przygotowanie powtórnego uruchomienia testu.

Meteory – schedulowanie

Kolejnym naszym posunięciem, który nie tylko pozwolił na następny krok w kierunku ograniczanie kosztów projektu, ale też skrócił czas potrzebny na strojenie systemu pod kątem wydajności, było zmierzenie się z tematem nocnych testów. Dlaczego nocnych – zapytacie? Już wyjaśniam. Ano dlatego, aby móc przeprowadzać testy systemów także w środowisku preprodukcyjnym. Preprodukcyjnym, czyli takim środowisku,które jest identyczne ze środowiskiem produkcyjnym. I nie byłoby tutaj problemu, gdyby nie fakt, iż część projektów jest wdrażanych na tym samym sprzęcie, na którym pracują już inne aplikacje produkcyjne.Uruchomienie w takiej sytuacji testów wydajnościowych nowego projektu może mieć wpływ na wydajność istniejących już systemów. Stąd właśnie konieczność przeprowadzania testów wydajnościowych w godzinach mniejszego ruchu. Początkowo prosiliśmy o pomoc w samym uruchomieniu testu naszych kolegów i koleżanki z działu utrzymania, który pracuje także w trybie nocnym. Zdarzało się też, iż sami czasem przychodziliśmy w środku nocy do biura. Zautomatyzowanie nocnych testów na platformie Meteorów poprzez wykorzystanie mechanizmu cron oraz opcji uruchamianie JMeter’a z linii poleceń, bez interfejsu GUI, pozwoliło na usunięcie powyższych niedogodności.

Praktyczne realizacje testów

Jednym z większych projektów, podczas którego Meteory były intensywnie wykorzystywane podczas prac nad strojeniem wydajności, był projekt nowej strony głównej Onet.pl z roku 2008. Zbudowane scenariusze testowe odzwierciedlały funkcjonalność panelu „Moje ulubione”.Największym wyzwaniem było tutaj zrównoważenie stopnia skomplikowania planu testów w odniesieniu do realnej mocy testowanego systemu.Musieliśmy także brać pod uwagę koszty związane z dokładaniem kolejnych węzłów do meteorów. Dlatego też w przypadku bardzo szczegółowych scenariuszy testowych, a także w przypadku bardzo dokładnego zapisywania wyników testu, wykorzystywaliśmy tylko jeden węzeł docelowy badanej architektury. Pozwoliło to na znaczne zredukowanie poziomu ruchu testowego. Niewątpliwie komfortową sytuacją było posiadanie środowiska preprodukcyjnego, a więc takiego, które podczas testów nie było  wykorzystywane przez naszych użytkowników. Nie jest to jednak częsta sytuacja w naszym portalu.

Test nowego serwisu

Na diagramie poniżej przykładowy raport z testu wydajnościowego jednego z wielu naszych serwisów. Raport składa się z dwóch kolumn.

W lewej kolumnie można zobaczyć jak zachowywał się testowany serwis w trakcie testów. Pisząc serwis mam oczywiście na myśli nie tylko warstwę WWW, ale także główne warstwy backendowe, takie jak: warstwa aplikacyjna i warstwa bazodanowa. Zwrócenie uwagi na zachowanie się testowanego serwisu jest niezwykle istotne dla zapewnienia, iż proces testowy przebiega poprawnie. Można się dobrze do tego przygotować poprzez np. dokumentację projektową, w tym diagramy wdrożeniowe UML. W przykładzie tutaj prezentowanym mierzone są takie parametry, jak:wielkość ruchu, występujące błędy, obciążenie serwera. Ładnie widać tzw. „kominy”, czyli przebieg poszczególnych scenariuszy testowych.Ułożenie wszystkich wykresów jeden pod drugim niezwykle ułatwia późniejszą analizę wyników, ułatwiając np. korelację między zwiększonym ruchem a zwiększonym zużyciem CPU.

W prawej kolumnie prezentowane są wyniki uzyskane już z samego JMeter’a. Są tutaj prezentowane czasy odpowiedzi poszczególnych elementów systemu względem narastającej liczby równoczesnych użytkowników. Jak można się spodziewać, wraz ze wzrostem liczby użytkowników czasy te rosną.

Test wyszukiwarki

Innym przykładem tutaj prezentowanym są testy jednej z wielu naszych wyszukiwarek. Poniżej znajdują się zobrazowane w postaci wykresów wyniki testów wydajnościowych. Na górnym wykresie prezentowane są czasy odpowiedzi, na dolnym natomiast widać osiągniętą wydajność w odsłonach na sekundę. Test był wykonywany 2 razy w odstępie kilkunastu dni i jak widać drugi przebieg posiada zdecydowanie lepsze parametry wydajnościowe, zwłaszcza pod kątem osiągniętej liczby odsłon. Stanowi to potwierdzenie, iż zespół developerski zwiększył swoimi pracami wydajność wyszukiwarki.

Podsumowanie

Zachęcam Was do skorzystania z JMeter’a. W portalu Onet.plsprawdziło się to narzędzie, głównie poprzez swoją prostotę, a takżełatwość dostosowywania do specyfiki danych testów. Więcej o samymnarzędziu można się dowiedziec pod adresem http://jakarta.apache.org/jmeter . Zapraszam Was do opisywania swoich doświadczeń w komentarzach do tego artykułu.

Jacek Książek
Kierownik Działu Jakości i utrzymania