Wir haben im ersten Teil gezeigt, wie ein Lasttest für eine Vaadin-Anwendung mit dem OpenSource-Programm JMeter aufgebaut werden kann. Als Beispiel diente der Officewerker, eine Anwendung zum Office-Management in kleinen Unternehmen oder Teams. Dieser Artikel – wieder auf Basis des Officewerkers – beleuchtet nun eine konkrete Testreihe auf der Cloud-Plattform EC² (Elastic Computing Cloud) von Amazon. Der Fokus liegt dabei auf dem Antwortzeitverhalten bei immer mehr Anfragen – und den entstehenden Bottlenecks. Dabei beleuchten wir vor allem die Rolle von Vaadin.
Zur Durchführung des Tests verwenden wir zwei Server auf der EC²:
- Einen Server als Application Server für den Officewerker – dieser Server wird unter Last gesetzt.
- Einen Server zur Ausführung des Testprogramms unter JMeter – dieser Server erzeugt die Last.
Die Server sind wie folgt ausgestattet:
RAM | Cores | |
Server unter Last | 15 GB | 8 Cores |
Test-Treiber-Server | 7,5 GB | 4 Cores |
Da sich beide Server im EC²-Netz befinden, ist von einem sehr performanten Netzwerk mit vernachlässigbarem Einfluss auszugehen. Das JMeter-Testprogramm simuliert die vom Browser gestellten Netzwerk-Anfragen. Ziel des Tests ist also die Server-Seite von Vaadin.
Was wir also nicht testen, ist die Performance des Netzwerks (auf die Vaadin keinen Einfluss hat) und die Client-Seite von Vaadin. Da diese allerdings nur genau eine Sitzung bedient, ist sie nach unserem Dafürhalten zunächst vernachlässigbar. Die Möglichkeit eines „sofortigen“ Tests einer Vaadin Anwendung im eigenen Browser bieten die Beispiel-Anwendungen von Vaadin unter https://vaadin.com/demo
Der Test führt nun eine Reihe von Aktionen durch:
- Aufruf der Startseite
- Laden der Ressourcen (JavaScripts, Bilder, etc.) für eine realistische Simulation
- Einloggen (Schritt 1)
- Wechsel auf die Startseite (Schritt 2)
- Wechsel auf die Liste der Eingangsrechnungen (Schritt 3)
- Suche nach einer Rechnungsnummer (Schritt 4)
Die Schritte 2 und 3 vernachlässigen wir hier, da weder in der UI- noch in der Business-Schicht etwas Spannendes passiert. Diese beiden Schritte waren auch bei der Performance-Messung unauffällig. Daher werden wir im Folgenden die Schritte 1 und 4 mitsamt deren Spezifika näher beleuchten.
Test von Schritt 1: Einloggen
Die folgende Tabelle zeigt die Ergebnisse von drei Läufen mit JMeter. Die Spalten haben dabei folgende Bedeutungen:
- Threads – Anzahl der Threads, die gleichzeitig auf die Anwendung zugreifen
- Durchläufe – Anzahl der Durchläufe, die jede Thread durchführt
- # – Anzahl der Ausführungen von Schritt 1 (Logins)
- Avg – Durchschnittliche Antwortzeit
- Dev –Standardabweichung von der durchschnittlichen Antwortzeit
Threads | Durchläufe | # | Avg [ms] | Dev [ms] |
50 | 20 | 1000 | 4800 | 1191,55 |
100 | 20 | 2000 | 9335 | 2332,37 |
200 | 20 | 4000 | 19423 | 4504,16 |
Dabei wird deutlich, dass ein praktisch lineares Wachstum vorliegt. Sprich: je mehr simulierte Nutzer gleichzeitig auf die Anwendung zugreifen, desto länger müssen diese Nutzer beim Login warten.
Es ist darüber hinaus evident, dass das Ergebnis schwer als zufriedenstellend betrachtet werden kann. Die Vermutung, dass lineares Wachstum (oft) durch Thread-Synchronisation hervorgerufen wird, bestätigt sich beim Blick in den Quelltext: Bei der Anmeldung wird synchronisiert auf ein Objekt zugegriffen, das Session-übergreifend verwendet wird.
Wenn die Stelle im Quelltext nicht so offensichtlich wie in unserem Beispiel ist, können derartige Probleme auch über Tools (z.B. JVisualVM) aufgespürt werden. Auch lässt sich der Anteil am Zeitverbrauch von Vaadin, der Geschäftslogik und des Anwendungsservers genauer aufschlüsseln. Im übernächsten Abschnitt beschreiben wir dies genauer.
Test von Schritt 4: Suche nach einer Rechnungsnummer
Die Ergebnisse des Tests sind wieder in einer Tabelle dargestellt. Folgende Spalten sind hinzugekommen bzw. haben eine andere Bedeutung:
- Rechnungen – Anzahl der Rechnungen, die pro Durchlauf gesucht werden
- Sockets/DB – Anzahl der Datenbankverdingungen aus dem Application Server zur Datenbank
- # – Anzahl Ausführungen von Schritt 4
Threads | Durchläufe | Rechnungen | Sockets (DB) | # | Avg [ms] | Dev [ms] |
50 | 20 | 10 | 14 | 10000 | 71 | 53,41 |
100 | 20 | 10 | 12 | 20000 | 70 | 50,20 |
200 | 20 | 10 | 14 | 40000 | 72 | 76,03 |
Dieser Test hat nun eindeutig kein lineares Wachstum. Vielmehr bleibt das Antwortzeitverhalten bei der Verdopplung von 50 auf 100 unverändert. Gleiches gilt für die der Erhöhung von 100 auf 200 simulierte parallele Benutzer. Lediglich die Streuung um den Mittelwert (Standardabweichung) steigt etwas an.
Es ist an dieser Stelle entscheidend, dass pro Request eine andere Rechnungsnummer abgefragt wird – sprich: es erfolgt bei jeder Anfrage ein Zugriff von Vaadin über die Business-Schicht bis in die Datenbank. Der durchschnittliche Zeitbedarf hierfür beschränkt sich auf nicht wahrnehmbare ~70 Millisekunden für jede der gezogenen 40.000 Rechnungen. 3 von 4 Anfragen sind in weniger als ~150 Millisekunden abgearbeitet.
Dies lässt den Schluss zu, dass das Antwortverhalten vor allem vom Backend hinter Vaadin abhängig ist. Ist dieses (wie im Schritt 1 erkannt) nicht effizient, ist es auch die Anwendung in Summe nicht. Ist es allerdings (wie in Schritt 4 gemessen und aufgezeigt) effizient, dann ist auch die Anwendung in Summe effizient.
Um diese These weiter zu härten haben wir die Last auf Schritt 4 weiter erhöht, und zwar um das 50-fache auf 500 abgerufene Rechnungen.
Test von Schritt 4: Suche nach einer Rechnungsnummer II – modifiziert
Threads | Durchl. | Rechnungen | Sockets (DB) | # | Avg [ms] | Dev [ms] |
200 | 20 | 10 | 14 | 40000 | 72 | 76,03 |
200 | 20 | 500 | 32 | 197170 | 2380 | 782,58 |
Anmerkung: Der Test in der zweiten Zeile wurde aus Zeitgründen nach ca. 10% Fortschritt abgebrochen.
Bei diesem Test mit erheblich mehr Datenbankabfragen wird eine deutlich höhere Last auf dem Backend erwartet. Die obige Tabelle zeigt für den Sprung von 10 auf 500 Rechnungs-Abfragen pro Benutzer (also auf das 50-fache) eine ver-47-Fachung der Antwortzeit an. Um diesem Phänomen auf den Grund zu gehen, analysieren wir nun eine Stufe tiefer: Wir betrachten die Zeit, die entlang des Aufrufs von Vaadin über die Business-Schicht (in Form von EJBs) bis in die Datenbank jeweils in den Methoden verbracht wird („Self Time“ – sie ist eine „Wall Clock Time“, sie betrachtet also nicht den CPU-Verbrauch, sondern den für uns hier interessanten Zeitverbrauch für die Methode).
Für die Analyse haben wir auf JVisualVM (http://docs.oracle.com/javase/6/docs/technotes/tools/share/jvisualvm.html) zurückgegriffen, die einen detaillierten Einblick in JVMs (auch in entfernte) ermöglicht.
Das Ergebnis ist in der folgenden Grafik dargestellt:
Der Vollständigkeit halber haben wir auch untersucht, welche Zeit auf die Verbrauchs-intensivste Vaadin-Methode entfällt.
Dieses Ergebnis zeigt sehr deutlich, dass die Persistenzschicht den Löwenanteil der Aufrufzeit verbraucht. Alleine die erste Methode zeichnet sich für 57% der Antwortzeit verantwortlich.
Betrachtet man die ersten drei Methoden, so fällt auf, dass
- sich alle Methoden im Bereich der EJB-Schicht oder dahinter befinden – sprich: im Backend angesiedelt sind
- diese für 98% der gesamten Self-Time verantwortlich sind
Die Verdopplung der an die Datenbank geöffneten Sockets (vgl. obige Tabelle) unterstreicht diese Erkenntnis abermals. Dem gegenüber liegt die in Bezug auf Zeitverbrauch „teuerste“ Methode aus dem Vaadin-Framework im nicht mehr messbaren Bereich (0%).
Fazit
Damit ist auch hier festzuhalten, dass die Performance einer Vaadin-Anwendung (zumindest was die Antwortzeit betrifft) durch die Performance des Backends konstitutiv bestimmt ist. Das Bottleneck war in Schritt 1 die synchronisierte Business-Logik und in Schritt 4 bei entsprechender Last die Datenbank. In beiden Fällen gilt es, das Backend des Officewerker nachzubessern. Die Bereitstellung der UI über Vaadin hat einen vernachlässigbar geringen Anteil an der Antwortzeit. Die Anwendung ist so performant (oder so nicht-performant) wie ihr Backend.
Im dritten und letzten Teil beleuchten wir den Speicherverbrauch von Vaadin während der Lasttests.
Wenn Sie Fragen haben, schreiben Sie einfach einen Kommentar oder schreiben Sie uns eine E-Mail:
oliver.damm [at] akquinet.de
sebastian.rothbucher [at] akquinet.de
Ein Gedanke zu „Vaadin unter Last – Teil 2: Ergebnisse der Lasttests (Antwortzeit)“
Kommentare sind geschlossen.