Lasttests mit dem Werkzeug Gatling
Erfahrungsbericht eines LoadRunner Lasttesters
Stephan Dannewitz - August 2017Motivation für den Review von Gatling
QMETHODS führt seit über 17 Jahren Lasttests für Kunden in Softwareentwicklungs-
und IT-Projekten durch. Auf Grund der großen Spannbreite an eingesetzten Technologien
wie HTTP, WebServices, Java, RMI, SQL, RDP, Citrix etc. kommt meist das Lasttest-Werkzeug
LoadRunner zum Einsatz.
Als Lasttester kommt man an dem Werkzeug Gatling (Wortbedeutung: automatische
Schusswaffe) nicht vorbei. Mich hat in erster Linie der Non-Blocking-I/O gereizt,
mir das Lasttest-Werkzeug genauer anzuschauen.
Automation von Geschäftsprozessen in Gatling
Für die Erstellung eines aussagekräftigen Lasttests ist die technische Abbildung
von Geschäftsprozessen notwendig. In Gatling werden die Geschäftsprozesse als 'Szenario'
bezeichnet. Diese Szenarien können aus mehreren Aktionen bestehen, die wiederum innerhalb
von Objekten (als Methoden) implementiert und beliebig kombiniert werden können. Die
Unterteilung in Objekte und deren Methoden ist nicht zwangsläufig notwendig, wird
aber aufgrund der Übersichtlichkeit empfohlen.
Als Beispiel nutzen wir unsere lokale Atlassian Jira Plattform. Hierbei wird die
Startseite von Jira aufgerufen, die Benutzeranmeldung durchgeführt, nach dem Begriff
'Gatling' gesucht und abschließend der Benutzer wieder von Jira abgemeldet.
Das Szenario erhält den Namen 'Beispiel_Jira' und ruft die Methoden ('Login',
'Search' etc.) aus dem Objekt 'Jira' auf. Ein zusätzliches Szenario 'Beispiel_Jira_Peak'
dient zur Erzeugung einer kurzzeitigen Peak-Last. Durch die Angabe der Laufzeit im
Szenario ist leider die Wiederverwendung von Szenarien eingeschränkt. Diese wäre besser
in der Konfiguration der Simulation aufgehoben.
val scn1 = scenario("Beispiel_Jira").during(3 minutes){
exec(Jira.GoTo).exec(Jira.Login).exec(Jira.Search).exec(Jira.Logout)}
val scn2 = scenario("Beispiel_Jira_Peak").during(60 seconds){
exec(Jira.GoTo).exec(Jira.Login).exec(Jira.Search).exec(Jira.Logout)}
Code-Beispiel: Zusammenstellung von Szenarien auf Basis der Aktionen
Die Implementierung eines Prozessschrittes ist recht selbsterklärend, wie das
folgende Code-Beispiel anhand des Jira-Logins zeigt:
- Ausführung eines POST-Request inklusive der Parameter für Benutzernamen und Passwort
- Prüfung auf Existenz eines Tokens im Response-Cookie
- Speicherung des Tokens in der Variable 'Token' zur späteren Nutzung
- Prüfung auf eine erfolgreiche serverseitige Ausführung
- Pausieren des Skriptes für 1 Sekunde
object Jira {
val Login = {
group("Login_Group"){
exec(http("Login")
.post("/rest/gadget/1.0/login")
.formParam("os_username", "Username")
.formParam("os_password", "Password")
.check(headerRegExp("Set-Cookie", "atlassian.xsrf.token=(.*?);")
.find.saveAs("Token"))
.check(status.is(200)))}
.pause(1)
}
...
}
Code-Beispiel: Objekt, Methoden und Szenario in Gatling definieren
Die Server-Response enthält in diesem Fall Cookies, in denen die SessionID und
das Token enthalten sind. Gatling übernimmt automatisch für jeden VUser (virtueller
Benutzer) das Cookie-Management. Daher ist hier kein Korrelieren notwendig.
Noch ein weiteres Beispiel: Um sicherzustellen, dass die Methode 'Search' erfolgreich
war, lässt sich mit 'checks' der Inhalt der Seite hinsichtlich der Suchergebnisse
überprüfen. In diesem Fall wird nach einem spezifischen Jira-Vorgang gesucht, der
nur nach erfolgreichem Login und erfolgreicher Suche angezeigt wird.
.exec(http("Suche verifizieren")
.get("/browse/QI-627?jql=text%20~%20%22gatling")
.check(RegExp("Gatling Blogeintrag erarbeiten")))
Code-Beispiel: Verifizierung einer Aktion mittels RegExp
Dynamische Daten aus der Anwendung können manuell mittels RegExp erfasst, in einer
Variable gespeichert und an beliebiger Stelle wiederverwendet werden.
<!-- Das xsrf-Token wird während des Logins aus dem gesetzten Cookie extrahiert
und in der Variable "Token" gespeichert -->
.check(headerRegExp("Set-Cookie", "atlassian.xsrf.token=(.*?);").find.saveAs("Token"))
<!-- Im Logout-Prozess muss das Token an die URL angehängt werden -->
val Logout = {
group("Logout"){
exec(http("Logout")
.get("/secure/Logout!default.jspa?atl_token="+"${Token}")}
Code-Beispiel: Korrelation dynamischer Daten
Erstellung und Durchführung einer Lasttest-Simulation mit Gatling
Nach erfolgreicher Automation der Geschäftsprozesse in Form von Szenarien ist
das Ausführungsverhalten dieser zu definieren. Dieses wird bei Gatling als Simulation
bezeichnet. Es können die Anzahl der Benutzer, das Anlaufverhalten (Ramp-up), die
maximale Laufzeit und viele weitere Parameter definiert werden:
Detaillierte Parameterliste für die Definition des Lastverhaltens
In unserem Beispiel habe ich die erste Simulation wie folgt definiert: 5 Benutzer
starten über einen Zeitraum von 10 Sekunden und führen das Szenario über 3 Minuten
immer wieder von vorn durch (Achtung: Die 3 Minuten sind im obigen Szenario definiert
worden).
In der zweiten Simulation wird nach 60 Sekunden eine Peak-Last mit 25 weiteren
Benutzern über 60 Sekunden erzeugt.
setUp(
scn1.inject(rampUsers(5) over(10 seconds)),
scn2.inject(nothingFor(60 seconds), atOnceUsers(25))
).protocols(httpProtocol)
Code-Beispiel: Konfiguration der Gatling Simulation
Während der Ausführung eines Lasttests werden dem Benutzer über die Konsole zyklisch
Basisinformationen über den Ausführungsstatus ausgegeben. Mh, das war mir dann doch
etwas zu rudimentär!
Abbildung: Ausgabe zum Status des Lasttests in der Konsole
Für ein übersichtliches Live-Monitoring bietet Gatling die hauseigene, kostenpflichtige
Erweiterung "Gatling Frontline" an.
Gatling Frontline
Analyse der Ergebnisse des Gatling Lasttests
Nach erfolgreicher Durchführung des Lasttests generiert Gatling ein HTML-Dokument
mit den Testergebnissen. Hier ist eine begrenzte Anzahl an Grafiken und Tabellen fest
vordefiniert, die jedoch nicht projektspezifisch erweiterbar sind. Einige Beispiele
sind im Folgenden erläutert.
Folgende Abbildung visualisiert noch einmal das in der Simulation konfigurierte
Verhalten hinsichtlich der Benutzer und kann helfen entsprechende Fehlkonfigurationen
zu erkennen.
Abbildung: Anzahl der von Gatling simulierten Benutzer über den Lasttest-Zeitraum
Der Klassiker ist natürlich die tabellarische Übersicht über die Anzahl der Aufrufe
und deren Antwortzeiten zzgl. entsprechender Statistiken. Es ist sehr empfehlenswert
in den Szenarien die Group-Funktion zu verwenden, um die einzelnen Anfragen einem
Funktionsaufruf zuordnen zu können.
Abbildung: Anzahl der von Gatling ausgeführten Aufrufe und Antwortzeiten gruppiert
nach den Szenarien
Eine Visualisierung der Antwortzeiten mithilfe von Perzentilen ermöglicht die
Bewertung des Laufzeitverhaltens der Anwendung. Folgende Abbildung zeigt den deutlichen
Anstieg der Antwortzeit im Peak-Zeitraum. Hier ist wieder die Group-Funktion wichtig,
um auch auf Funktionsebene eine Bewertung durchführen zu können.
Abbildung: Antwortzeiten des Gatling-Lasttests visualisiert mit Perzentilen
Mein Fazit zu Gatling
Mit meinen LoadRunner-Erfahrungen konnte ich einen exemplarischen Lasttest zügig
umsetzen. Die in Gatling verwendete Begriffswelt mit Szenario und Simulation hat bei
der Diskussion mit meinem Kollegen allerdings öfters zu Missverständnissen geführt.
Sehr positiv ist mir aufgefallen, dass alle Lasttest-Artefakte in Form von Szenarien
und Simulationen in einem Skript abgelegt sind. Dies ist eine gute Voraussetzung für
die Versionierung im Entwicklungs-Branch und die Integration in den Testautomationsbereich
des DevOps-Prozesses.
Gatling kann im direkten Vergleich zu LoadRunner dank integrierter Non-Blocking-Technologie
ein Vielfaches an Last von einem Rechner aus erzeugen. Dies ist beim LoadRunner erst
unter Verwendung von mehreren Lasttreibern möglich. Gatling bietet dafür keine Out-of-the-Box-Lösung
für die Lastverteilung auf mehrere Rechner an.
Zur Verbesserung der Übersicht und Wiederverwendbarkeit ist ein Refactoring der
mit der GUI aufgezeichneten Skripte allerdings unerlässlich. Dieser zeitliche Mehraufwand
ist nicht zu unterschätzen und bringt einige Fallstricke mit sich.
Das fehlende Live-Dashboard während der Lasttest-Durchführung erschwert die Interpretation
über den Status des Lasttests (Anzahl Benutzer, Antwortzeiten, Ressourcenverbrauch
etc.). Da fühle ich mich beim LoadRunner mit dem Zugang zu allen benötigten Informationen
sicherer im Sattel!
Die Darstellung der Testergebnisse und die Analysemöglichkeiten fallen im Vergleich
zu LoadRunner etwas mau aus. In puncto Analysierbarkeit und Benutzerfreundlichkeit
kann Gatling dem LoadRunner somit nicht das Wasser reichen.
Trotz der Kritikpunkte ist Gatling ein mächtiges Open-Source-Werkzeug und kann
besonders mit der Erzeugung von hohen Lasten dank Non-Blocking-Technologie punkten!
Was ich positiv finde
- Hohe Anzahl an zu simulierenden Benutzern mittels Non-Blocking-Technologie.
- All-in-One Skript mit Szenarien und Simulation für einfache Handhabung und DevOps-Integration.
- Einfache Installation unter Linux und Windows.
- Kostenfreie Open-Source-Lösung.
Wo ich Möglichkeiten zur Verbesserung sehe
- Schwieriger Einstieg für Neulinge im Bereich Lasttest mangels Benutzerführung durch
GUI.
- Keine werkzeugbasierte Unterstützung für die Korrelation der Szenarien bzw. Analyse
der Lauffähigkeit dieser (vgl. Wizards im LoadRunner).
- Live-Monitoring während der Durchführung des Lasttests nur mit kostenpflichtiger Erweiterung
"Gatling FrontLine" möglich.
- Keine Möglichkeit zur Verteilung der Testausführung auf mehrere Lasttreiber.
- Die Ausgabe der Testergebnisse basiert auf einem nicht anpassbaren bzw. erweiterbaren
HTML-Report, was die Analyse und Auswertung erschwert.
- Im Szenario muss bereits die Ausführungsdauer angegeben werden. Diese wäre besser
in der Simulation zu definieren, um die Wiederverwendbarkeit der Szenarien zu erhöhen.
- Keine Möglichkeit ein Herunterfahren (Ramp-down) der virtuellen Benutzer in der Simulation
zu definieren.
- Durch die noch kleine Community und die teilweise spärliche Dokumentation ist es schwierig,
auf komplexe Fragen oder technische Details Antworten zu finden.
In unserem QMETHODS-GitHub finden Sie das vollständige Gatling-Lasttest-Skript
sowie einen Lasttest-Ergebnisreport im HTML-Format zum Herunterladen.
-
Gatling Webseite
Gatling Frontline - kostenpflichtige Erweiterung für Live-Dashboards
Begriff Gatling (Wikipedia)
Keywords
DevOps
Gatling