E-sklepy, które dają radę – o testach wydajnościowych w Media4U

Testy serwisów internetowych zwykle kojarzą się z testami funkcjonalnymi. W ich ramach następuje sprawdzanie, czy dana funkcja serwisu działa prawidłowo, czyli zgodnie ze specyfikacją. Wyobraźmy sobie sytuację: posiadamy uruchomiony sklep internetowy. Każdy jego element był poddawany wystarczającej liczbie przypadków testowych i wszystko działa jak należy… do czasu.

Rusza akcja marketingowa. Ruch użytkowników sklepu rośnie, ale czas odpowiedzi serwera również. W pewnym momencie sklep przestaje odpowiadać, a klienci tracą cierpliwość. Jeśli taka sytuacja zaskoczyła właściciela e-sklepu, to znaczy, że na etapie wytwarzania oprogramowania zapomniano o przeprowadzeniu testów wydajnościowych.

Po co to komu?

Co dają nam testy wydajności? Przede wszystkim udzielają odpowiedzi na poniższe pytania:

  1. Umowa z klientem zawiera informację, że sklep ma utrzymać ruch 2.000 użytkowników poruszających się po serwisie. Czy spełniamy już ten warunek, tzn. czy czasy odpowiedzi serwera przy tym ruchu są na akceptowalnym poziomie?
  2. Jakie miejsca są tzw. „wąskimi gardłami” – czyli, które punkty serwisu są najbardziej obciążające dla serwera www lub bazy danych? Są to jednocześnie potencjalni kandydaci do dalszej optymalizacji.
  3. Czy zmiany, które wprowadzamy w trakcie życia serwisu, miały wpływ na poziom wydajności?

Testy w Media4U przeprowadzamy przy użyciu jednego z bardziej popularnych narzędzi – JMeter. Jest to aplikacja, która umożliwia symulację teoretycznie dowolnie dużego ruchu na stronie. Daje przy tym spore możliwości konfiguracji samego testu tak, aby był zbliżony do obciążenia generowanego przy rzeczywistym ruchu użytkowników.

testy_1

Widok narzędzia JMeter

 

Robimy to tak…

Budowanie testu zaczynamy od etapu analizy, gdzie z pomocą przychodzi narzędzie Google Analytics. Pozwala ono na analizę rzeczywistego ruchu w serwisach internetowych.
Dzięki niemu możemy dowiedzieć się, jaki jest rozkład użytkowników na stronie, czyli np. ilu z nich przegląda strony kategorii, ilu produktowe, ilu przechodzi do koszyka, czy jaki procent użytkowników składa zamówienie. Ta wiedza pozwala na odpowiednie skonfigurowanie grup użytkowników (Thread Group). Każda z grup odzwierciedla jedno z zachowań użytkowników. W grupie uruchomionych jest x wątków, a każdy z wątków odpowiada jednemu użytkownikowi. Każdy z tych wątków wykonuje serię requestów http (HTTP Request) , które są wykonywane w czasie prawdziwego ruchu na stronie.

Istotną rzeczą jest to, aby oprócz liczby wątków wziąć pod uwagę również częstotliwość wykonywania żądań, w celu uzyskania odpowiedniej liczby requestów na sekundę. Odpowiednią wartość, którą chcemy osiągnąć, możemy poznać, obserwując dane w Google Analytics. W celu uzyskania odpowiedniej częstotliwości wykonania requestów możemy w JMeterze użyć obiektów typu Timer (np. GaussianRandomTimer) . Modyfikując parametry Timera i znając liczby requestów dla każdej z grup możemy wyliczyć, jakie powinny być średnie przerwy między kolejnymi żądaniami, aby uzyskać zamierzoną częstotliwość. Jest to bardzo istotne, ponieważ jeśli założymy sobie, że dana grupa symuluje pewną liczbę użytkowników, a częstotliwość requestów będzie zbyt duża, okaże się, że w rzeczywistości wygenerowaliśmy dużo większe obciążenie serwera, niż planowaliśmy.

Najlepszy sposób na zweryfikowanie, czy konfiguracja testu jest prawidłowa, to podpięcie testowanego serwisu do Google Analytics i obserwowanie ruchu, który generujemy, za pomocą JMetera.

Trzeba tu zaznaczyć, że uruchomienie testu JMetera bez żadnych modyfikacji nie pokaże nam rezultatu w statystykach Google Analytics, ponieważ JMeter nie działa jak przeglądarka i nie wykonuje kodu Java Script zawartego w treści strony.

Jednym z możliwych obejść jest wplecenie w plan testów takich samych requestów http, jakie wysyła skrypt Google Analytics po uruchomieniu Java Scriptu w przeglądarce.

W tym celu wchodząc na testowany serwis, który już jest spięty z Google Analytics,
za pomocą Firebuga możemy sprawdzić, jak wyglądają requesty wysyłane do Google Analytics. Gdy wiemy, jak wyglądają takie żądania, możemy je dodać do naszego testu za pomocą obiektów HTTP Request. Uruchamiając test, zobaczymy w Google Analytics ruch, który generują powyższe żądania. Daje to możliwość oceny, czy konstrukcja testu spełnia założenia. Oczywiście w czasie właściwego testowania wydajności requesty wysyłane do Google Analytics zostają wyłączone, aby nie stwarzać dodatkowego obciążenia dla samego JMetera i żeby odpowiedzi od serwera Google nie zaburzały rezultatów z  testowanego serwera.

Należy zwrócić uwagę, aby maszyna, na której działa JMeter, nie była przeciążona, dlatego nie można uruchomić zbyt dużej liczby wątków na jednym komputerze. Gdyby tak się stało, czasy odpowiedzi serwera logowane przez JMeter będą niezgodne ze stanem faktycznym. Gdy chcemy uzyskać większy ruch, należy uruchomić test na odpowiedniej liczbie równolegle działających komputerów. Nie można łatwo odpowiedzieć na pytanie: jaki ruch może wygenerować pojedynczy komputer, aby nie zaburzyło to otrzymywanych rezultatów.
Zależy to od złożoności samego testu i liczbie uruchomionych „listenerów”, czyli modułów do przetwarzania rezultatów testu. W praktyce przy naszych testach nie przekraczamy liczby 600 użytkowników na jednej instancji JMetera.

Dobrą praktyką jest tutaj zastosowanie najprostszego z listenerów – „Simple data writer”, który jedynie zapisuje czasy odpowiedzi próbek do pliku CSV. Nie generuje on raportów „w locie”, co znacząco zmniejsza obciążenie komputera zbierającego wyniki. Plik CSV można potem wykorzystać do wygenerowania bardziej złożonych raportów. Na przykład raportu „Summary Report” prezentującego zbiorcze wyniki przeprowadzonego testu:

Przykładowy widok raportu w Summary Report

Przykładowy widok raportu Summary Report

…i tak

Często stosowaną metodą, również poprawiającą wydajność komputera, na którym uruchamiamy JMetera, jest wykluczenie z testu zasobów statycznych, takich jak pliki graficzne czy pliki css. Mają one zwykle znikomy wpływ na wydajność serwera, a dają duży narzut na liczbę rezultatów, które musi przetworzyć JMeter oraz na zajęcie łącza sieciowego.

Przed uruchomieniem testu dobrze jest też rozłożyć przyrost ruchu w czasie. Wygodnie można to skonfigurować, definiując grupy wątków użytkownika z wykorzystaniem „Stepping thread group” (dostępne jako plugin: http://jmeter-plugins.org/wiki/SteppingThreadGroup/).

Uruchomienie wszystkich wątków jednocześnie dałoby w efekcie zbyt duże, nienaturalne obciążenie testowanego serwera. Test powinien trwać też dostatecznie długo, by wielokrotnie wykonać te same kroki. Wykonanie ścieżki testu tylko jeden raz dałoby nam chwilowy rezultat, z którego trudno wyciągnąć prawidłowe wnioski. Często jest tak, że problem widzimy dopiero po pewnym czasie, gdy np. zaczynają się kolejkować zapytania do bazy danych. Dlatego też w czasie trwania testu powinniśmy monitorować logi serwera bazodanowego i  www. Da to większą możliwość lokalizacji źródła ewentualnych problemów wydajnościowych.

Każdy projekt – szczególnie sklepy internetowe – wymaga stałego rozwijania, wprowadzania nowych funkcjonalności w celu zwiększenia sprzedaży i nadążania za trendami rynku.
To powoduje, że zmienia się kod, zmieniają się zatem uwarunkowania. Efekt zmian zawsze powinien być monitorowany przez doświadczonego testera, który po wdrożeniu nowej wersji sprawdza, czy serwis nadal jest w stanie przyjąć zakładaną początkowo liczba użytkowników.

 

 

 

Dodaj komentarz