2012. február 1., szerda

JMeter - Webalkalmazások terhelési tesztelése

A Selenium-hoz hasonlóan már több projekt keretében is használtam a JMeter-t, így most elérkezett az idő hogy összefoglaljam a személyes tapasztalataimat egy gyakorlatias leírás keretében.

A JMeter segítségével kliens-szerver alapú alkalmazások teljesítményét tudjuk megvizsgálni különböző terhelési szinteken. Megtekinthetjük, hogy hogyan reagálna a hétköznapi terhelésre a web-alkalmazásunk, de akár azt is megtudhatjuk hogy melyik komponens lenne a szűk keresztmetszet egy nemvárt nagyobb terhelés esetén. Bár a mostani bejegyzésemben a webalkalmazások terhelési tesztelésére fogok szorítkozni, a JMeter lehetőséget ad web-szolgáltatások, ftp szerver vagy éppen adatbázis szerver tesztelésére is. A webalkalmazások tesztelésénél a JMeter alapvetően HTTP kéréseket küld és fogad, de eltérően a böngészőktől nem futtatja le a JavaScripteket és nem is jeleníti meg az oldalt, így ezek az idők nem fognak szerepelni a mért adatokban.

Érdemes megemlíteni, hogy az Apache JMeter-t nemcsak teljesítmény teszteléskor, hanem bármikor bevethetjük amikor hosszabb ideig tartó folyamatos terhelést szeretnénk generálni. Ilyen eset lehet például a performancia tuningolásához szükséges realisztikus terhelés generálása vagy egy hosszabb web-alkalmazás futtatás végrehajtása a memória szivárgások kimutatásához.

A használathoz először is töltsük le a JMeter 2.5-ös verzióját, majd indítsuk el a java -Xms512m -Xmx512m -XX:MaxPermSize=512m -jar ApacheJMeter.jar paranccsal, legalább ekkora memória beállítások használatával. A JMeter elindulása után megjelennek a TestPlan és a WorkBench csomópontok a baloldali panelon. A TestPlan lesz a tesztesetünk gyökér csomópontja, ami alá egyből vegyünk is fel egy ThreadGroup (TestPlan jobb klikk/add/Threads/ThreadGroup) elemet.

A ThreadGroup-nál definiált szálak (number of threads) egy-egy konkurens felhasználót fognak reprezentálni a tesztelés során, amelyek egymástól függetlenül hajtják majd végre az elkészített tesztesetet. Ugyanitt megadható a felfutási idő (Ramp-Up Period), azaz hogy hány másodperc teljen el amíg az összes szál (mint felhasználó) elkezdi a futását. Pl. ha a felhasználók száma 50, a felfutási idő 25 másodperc, akkor másodpercenként 2 új szál lesz elindítva. A lefutások számával (loop count) pedig megadhatjuk, hogy felhasználónként hányszor legyen a teszt végrehajtva vagy beállíthatjuk azt is, hogy folyamatosan fusson (forever).


A szerverhez küldendő kéréseket mintákkal (Samplers) adhatjuk meg. A JMeter sokféle kérés típust támogat, többek között a JMS, JDBC, FTP, LDAP, AJP, TCP, SOAP kéréseket, azonban most csak HTTP ill. HTTPS kérésekkel fogok dolgozni. A vezérlők (Logic Controllers), lehetőséget adnak hogy a minták küldéséhez valamilyen logikát is rendeljünk. (pl.:feltétel, ciklus, véletlenszerű választás kérések között stb...).

A HTTP kérések egyenkénti "kézzel" történő felvétele, majd az attribútumok beállítása sok időt vehet igénybe, így célszerű a JMeter HTTP Proxy Server lehetőségét kihasználni, ami lehetővé teszi hogy a böngészőben végrehajtott HTTP kéréseket automatikusan rögzítsük a JMeter-es tesztesetünkbe. Ehhez először is a ThreadGroup-hoz vegyünk fel egy Recording Controller-t, ami alá a HTTP Proxy Server majd automatikusan beteszi a rögzített HTTP mintákat.

A Recording Controller-hez ezután adjuk hozzá a következő konfigurációs elemeket (Configuration Elements), melyek mindig az adott scope elején - azaz a minták előtt - kerülnek feldolgozásra: HTTP Request Defaults, HTTP Header Manager, HTTP Cookie Manager. A HTTP Request Defaults-al alapértelmezett értékeket (pl. host, port) adhatunk meg az aktuális scope-hoz tartozó HTTP kéréseket reprezentáló mintáknak, a HTTP Header Manager segítségével pedig felülírhatjuk a HTTP fejléc információit (pl. user-agent). A HTTP Cookie Manager hozzáadásával, a rögzített mintákhoz tartozó cookie információk elmentődnek és a kérésekkel továbbítódnak.

Végül vegyük fel a HTTP Proxy Server-t (WorkBench/add/Non-Test Elements/ HTTP Proxy Server) a WorkBench csomópont alá, majd az alábbi ábra alapján töltsük ki a mezőket.


A port mezőnél adjunk meg egy szabad portot amit majd a böngésző proxy beállításainál is állítsunk be a HTTP és a HTTPS protokollokhoz. Ezután válasszuk ki az általunk létrehozott Recording Controllert és adjuk meg, hogy az egyes oldalakhoz tartozó kéréseket külön Controller-be tegye. Válasszuk ki a HTTP Header mentését és a mintákhoz a HTTP4Client típust. Az "URL Patterns to Include" résznél reguláris kifejezéssel megadhatjuk, hogy milyen URL-ekre érkező kérések legyenek rögzítve, a mezőt üresen hagyva minden kérés mentésre kerül! Az "URL Patterns to exclude"-nál pedig azt definiálhatjuk, hogy milyen kérések ne kerüljenek felvételre. Fontos, hogy a képeket, css, js stb. zárjuk ki mivel ezek a második lekéréstől kezdve már a browser cache-ből jönnek (de ezt azért ellenőrizzük le egy HTTPFox segítségével) így a folyamatos lekérésük torzítaná a mérési eredményeket. Az alábbi ábrán a Firefox proxy beállítása látható.


Ha ezzel megvagyunk nyomjunk rá a HTTP Proxy Server panel alján található Start gombra és a böngészőben menjünk végig azokon az oldalakon és akciókon amiket a tesztesetben felszeretnénk venni. A teszteset felvétele közben jól látható, hogy a HTTP kérések folyamatosan felvételre kerülnek a Recording Controller elemhez. A teszteset végén, a felvételt a Stop gombra való kattintással tudjuk leállítani. A minta kedvéért a tesztesetet egy portálon vettem fel ahol is a bejelenetkezés után megnéztem egy hírt és néhány infótár bejegyzést, majd kiléptem a felhasználóval, lásd a lenti ábrát.


A teszteset szépen alakul, azonban az indítás előtt még pár dolgot be kell állítani, de ezekről majd a következő részben fogok írni.

2012. január 18., szerda

Jenkins - Folyamatos integráció kialakítása

A folyamatos integráció egy olyan fejlesztési folyamat, ami hatékonyabbá teszi a csapatmunkában történő fejlesztést azáltal, hogy a fejlesztők gyakran (legalább naponta) és már a kezdetektől összeillesztik (integrálják) a kódjukat. A Continuous Integration arra a felismerésre épít, hogy a fejlesztés során a kódok integrációja a legproblematikusabb fázis és hogyha ezt korán lekezeljük akkor az esetleges problémák is gyorsabban javíthatóak lesznek!

A gyakorlatban ez úgy néz ki, hogy a fejlesztők bekommittolják a forráskód módosításaikat a verziókezelőbe, amiről a CI szerver értesül így frissíti a helyi kódbázisát majd lebuildeli a kódot és lefuttatja a teszteket, végül a build terméket kiteszi egy teszt szerverre ahol is a tesztelők egyből elkezdhetik a legfrissebb verzió tesztelését! Hibás build esetén a fejlesztők automatikusan visszacsatolást kapnak (email, sms, rss), így lehetővé válik a gyors beavatkozás a probléma elhárítása érdekében. Az értesítések mellett a CI szerverek lehetőséget adnak a buildek és a tesztek sikerességének időbeli követésére is egy dashboard-on keresztül.


Az előbb ismertetett folyamat akár manuálisan is elvégezhető lenne, azonban a CI szerverek segítségével ez kiválóan automatizálható és valóban egy gombnyomással minden elintézhető!

A piacon többféle kereskedelmi és open source CI szerver is megtalálható, a legelterjedtebb azonban mégis a Hudson ill. Jenkins a rengeteg rendelkezésre álló plugin-nak köszönhetően! Amikor az Oracle felvásárolta a SUN-t, a Hudson core fejlesztői létrehozták a Jenkins projectet, így a hasonlóság miatt a két CI szerver üzemeltetése és a konfigurálása szinte teljesen megegyezik.

Nemrég az én feladatom volt a céges folyamatos integráció bevezetése, így a következőkben megosztok egy-két hasznos tanácsot ezzel kapcsolatosan:
  • Hudson helyett használjunk inkább Jenkins-t, mivel az eredeti Hudson csapat fejleszti, dinamikusabban fejlődik és néhány plugin csak a Jenkins alatt érhető el!
  • Definiáljuk a JENKINS_HOME ill. JENKINS_BASE környezeti változókat!
  • A Jenkins jobok futtatását igény szerint állítsuk be kommitonként vagy napi egyszeri futtatáshoz (éjszakai build).
  • Archiváljuk a sikeres build termékeket (EAR, WAR) majd tegyük letölthetővé egy-egy link formájában.
  • Automatizáljuk a tesztek futtatását. (unit teszt, felületi teszt, integrációs teszt, performancia teszt)
  • Automatizáljuk a kód lefedettségi riportok futtatását.
  • Használjunk statikus kód ellenőrzőket a kódolási hibák kijelzésére és a cégen belüli kódolási konvenciók betartásához. (findbugs, pmd, checkstyle)
  • Sikertelen build esetére állítsunk be automatikus e-mail értesítőt, így a fejlesztők azonnal értesülnek a hibákról.
  • A webalkalmazás teszt szerverre történő telepítése után, hajtsunk végre egy egyszerű Smoke tesztet a telepítés sikerességének ellenőrzéséhez.
  • Aktiváljuk és használjuk a Jenkins security lehetőségeit.

Amennyiben a napi egyszeri build mellett döntünk, a web-alkalmazás telepítését követően érdemes automatizáltan lefuttatni egy 2-3 órás JMeter tesztet hétköznapi terhelést szimulálva, majd a teszt végén kigyűjteni a heap dump és verbose gc napló állományokat, melyeket a build termékek mellé is kirakhatunk, így szükség esetén gyorsan elővehetjük és analizálhatjuk. Sőt, a verbose gc információkból akár egyből egy diagramot is legenerálhatunk amit szintén betehetünk a build termékek közé!

Végül következzen egy-két hasznos Jenkins és Hudson plugin, amelyeket érdemes feltelepíteni:

A Jenkins további megismeréséhez és részletesebb konfigurációjához a Jenkins: The Definitive Guide ingyenesen letölthető e-könyvet ajánlom!

2012. január 4., szerda

Hasznos Eclipse pluginok Java alapú fejlesztéshez

Már elég régóta használok Eclipse-t a fejlesztéshez és mostanra összegyűlt pár hasznos plugin amiket mindig telepíteni szoktam, így most összeírtam ezeket. Az Eclipse Marketplace (Help/Eclipse Marketplace...) bevezetése óta, szerencsére a szükséges pluginok összevadászása is gyorsan megvan, nem kell sokat keresgélni.
JBoss, Hibernate és JSF alapú projectek fejlesztéséhez elengedhetetlen. Segítséget nyújt a projektek generálásához, kódok kiegészítéséhez, EJB-QL lekérdezések real-time teszteléséhez, JBoss ESB és JBPM-es fejlesztésekhez is.

JRebel plugin
A blogom olvasóinak gondolom nem kell bemutatnom a JRebel-t, nélkülözhetetlen eszköz Enterprise Java fejlesztéshez! A hozzákapcsolódó plugin megkönnyíti a telepítést és a konfigurálást is.

Eclipse Memory Analyzer plugin
Az EMA egy kiváló Java Heap analizáló kiterjesztés, ami segít a memory leak-ek megtalálásában, továbbá hasznos információkat szolgáltat arról, hogy milyen objektumok foglalják a memóriát! A legújabb fejlesztéseknek köszönhetően nemcsak SUN-os, hanem IBM Java-s heap dump-ot is analizálhatunk vele.
Log fájlok nézegetésére szolgáló plugin, a console view-hez hasonló működéssel. Erre a pluginra akkor volt szükségem amikor egy Websphere 6.1-es fejlesztésénél áttértünk a RAD folytonos belassulása miatt Eclipse-re és ott is fontos volt a napló állományok kényelmes követése. A plugin bevált, azóta is ezt használjuk!

Java Decompiler plugin (JAD)
Ez a tool lehetőséget ad a Java class fájlok visszafejtésére és analizálására. Hasznos lehet ha elveszett Java forrásainkat akarnánk a class fájlokból visszaállítani vagy ha egy nem open sorce Java library osztályainak tartalmába szeretnék betekintést nyerni! Van egy standalone verziója is JD-GUI néven.

Subclipse plugin
A népszerű Subversion-hoz (SVN) készült Eclipse plugin. Már régóta használom, gond nélkül működik.

FindBugs plugin 
A FindBugs felfedi a kódban a gyakori programozói hibákat, bad practice-eket és javaslatokat ad a kijavításukra. Pl.: objektumok összehasonlítása == operátorral; hashCode() nélküli equals() metódus; stb... Létezik még egy findbugs-contrib kiegészítő is, ami további hiba detektorokkal egészíti ki a keresést. Érdemes mind kettőt telepíteni!
A findbugs-hoz hasonló, potenciális Java hibák keresésére szolgáló plugin, ami segít megtalálni a nem optimális kódokat, lehetséges bugokat és a túlkomplikált kifejezéseket is. Jól paraméterezhető és egyszerűen szűkíthető a detektálandó hiba típusok köre, továbbá lehetőségünk van saját hiba detektáló kiterjesztéseket is beilleszteni! A PMD pluginhoz tartozik még egy paraméterezhető Copy-Paste-Detector (CPD), amivel segíthetünk kiiktatni ezt a rossz programozói szokást! :)

Checkstyle plugin
Szintén egy statikus kód ellenőrző plugin, azonban ezzel a kódolási standardokra fogalmazhatunk meg szabályokat. pl.: maximum 500 soros lehet egy Java osztály, legfeljebb 3 paramétere lehet egy metódusnak; a paraméternevek nem tartalmazhatnak ékezetes betűket; stb... A PMD-hez hasonlóan ez is jól paraméterezhető és egyedi szabályokkal is bővíthető.
Különböző metrikákat tudhatunk meg a kódunkról és az osztályok közötti csatolásról, melyeket grafikusan is megtekinthetünk! pl.: Ciklomatikus komplexitás; kohézió, stabilitás, stb...
A CodePro Analytix szintén egy hasznos tool amit a Google fejleszt. Az előbb említett statikus kód analizálók tulajdonságait ötvözi és kiegészíti kód lefedettség ellenőrzéssel valamint automatikus unit teszt generálással is, bár ez utóbbit azért kezeljük óvatosan! A statikus kód analizálók közül ez tekinthető a legteljesebbnek.


Érdemes még megnézni az Eclipse Marketplace toplistát, mert rátalálhatunk egy-két hasznos kiegészítőre! A jövőben még bővíteni fogom ezt a bejegyzést, így a későbbiekben is látogass majd vissza! .)