Shopware 6 Performance Blog
locust-main-image locust-main-image

Shopware 6 Lasttest/Benchmark mit Locust – Teil 1

Wenn Du einen Online-Shop auf Shopware 6 betreibst, ist es wichtig zu wissen, wie gut Deine Plattform unter Druck funktioniert. Gerade bei Aktionen wie Black Friday oder anderen Stoßzeiten ist es entscheidend, dass Dein Shop viele gleichzeitige Nutzer bewältigen kann, ohne Performance-Einbußen zu erleiden. Hier kommen Lasttests ins Spiel. In diesem Beitrag erfährst Du, was ein Lasttest ist, welche Tools dafür verfügbar sind, und warum Locust eine gute Wahl für Shopware 6 ist.

Im ersten Teil dieser Blogpost-Serie schauen wir uns die Theorie zu einem Lasttest an. In Teil 2 nächste Woche schauen wir uns einen Shopware 6 Lasttest in der Praxis an 🙂

Was ist ein Shopware 6 Lasttest?

Kurz gesagt simuliert ein Lasttest künstlich eine hohe Anzahl an Shopbesuchern. Ziel ist es herauszufinden, ob Dein Shop in speziellen Situationen mit mehr Traffic zurechtkommt.

Das ist gerade dann wichtig, wenn spezielle Aktionen wie Black-Friday, ein Newsletter mit einem großzügigen Angebot oder auch eine TV-Werbung geplant ist. Also immer dann, wenn mit mehr Besuchern als üblich gerechnet werden kann.

Da solche Aktionen meist bereits viel Geld in der Umsetzung kosten ist es besonders ärgerlich, wenn der Shop die zusätzliche Last gar nicht aushält, die Kunden nicht kaufen können und der erhoffte Umsatz ausbleibt. Am Ende sind sowohl der Shopbetreiber als auch die Kunden verärgert.

Um ein solches Horror-Szenario zu vermeiden, kannst Du mit einem Shopware 6 Lasttest relativ einfach vorher schauen, wie Dein Shop sich unter mehr Last verhält. Wenn die Last zu Problemen führt, können entsprechende Maßnahmen (z.B. die Datenbank optimieren) umgesetzt werden.

Welche Tools gibt es für einen Shopware Lasttest?

Aktuell gibt es eine Vielzahl von Tools, die Lasttests für Webanwendungen unterstützen und theoretisch benutzt werden können. Darunter zählen neben Locust auch Apache JMeter, Wrk, K6, Drill und und und.

Bisher habe ich neben Locust nur Erfahrung mit JMeter gemacht, was Shopware früher auch eingesetzt hat. Das Tool schien mir zumindest damals recht alt und hat mir bei einem Test auch nicht wirklich gefallen. Mit den anderen Tools habe ich bisher nicht viel Erfahrung gesammelt und kann dazu leider kein ausführliches Feedback geben.

Shopware 6 arbeitet unter anderem mit locust (zumindest hatten sie es für einen Augenblick im Shopware-Github-Repository eingebaut). Mit Locust konnte ich selbst etwas Erfahrung sammeln und es gefällt mir allgemein bereits sehr gut.

Welche Vorteile bietet uns Locust?

Locust ist basiert auf Python und ist ein leistungsstarkes Open-Source-Tool, das es Dir ermöglicht, reale Nutzeraktionen zu simulieren und die Performance Deiner Shopware 6 Plattform zu analysieren. Es ist besonders für seine Flexibilität und Benutzerfreundlichkeit bekannt. Hier die für mich wichtigsten Vorteile:

  • Einfache Implementierung: Locust ist in Python geschrieben, was es Entwicklern leicht macht, individuelle Testfälle zu erstellen. Du kannst z.B. simulieren, wie ein Nutzer Produkte durchstöbert, in den Warenkorb legt und einen Kauf abschließt. Ich selbst habe bisher sehr wenig Erfahrung mit Python gemacht, konnte den Code aber sehr leicht verstehen und selbst eigene Lasttests schreiben oder bestehenden Code erweitern.
  • Skalierbar: Ob Du 10 oder 10.000 Nutzer simulieren willst – bei Locust kann man die Anzahl der Besucher sehr leicht einstellen und das Tool sogar auf mehreren Maschinen parallel laufen, um eine große Anzahl an gleichzeitigen Besuchern zu emulieren.
  • Intuitive Web-Oberfläche: Während des Tests kannst Du die Ergebnisse in Echtzeit in der integrierten Web-UI verfolgen. Sie zeigt Dir sofort an, wie gut Dein System mit der Last zurechtkommt, und gibt Dir Einblicke in Ladezeiten, Fehlerquoten und vieles mehr.
  • Flexible Konfiguration: Da Du die Tests in Python schreibst, kannst Du das Verhalten der Nutzer exakt an die Abläufe in Deinem Shop anpassen, z.B. indem Du spezifische Seitenaufrufe oder Transaktionen simulierst.

Wie installiere ich Locust?

Installation

Um einen Lasttest mit Locust zu starten, musst Du im ersten Schritt locust installieren. Wie ich locust benutzte, zeige ich im nächsten Blogpost. Du kannst das Tool je nach Umgebung mit folgendem Befehl installieren:

pip3 install locust

Über folgenden Befehl kannst Du prüfen, ob das Tool richtig installiert ist:

locust -V

Unser erster Lasttest

Vereinfacht gesagt ist ein Locust Test nur ein Python-Programm, das verschiedene Requests an eine URL schickt. Als Ausgangspunkt brauchen wir hierbei immer eine sogenannte locustfile. Also eine Datei, die als Einstiegspunkt dient und in der unser Code steht. In meinem Case nenne ich die Datei locustfile.py

Die einfachste Version einer locustfile könnte folgendermaßen aussehen:

from locust import HttpUser, task

class HelloWorldUser(HttpUser):
    @task
    def hello_world(self):
        self.client.get("/hello")
        self.client.get("/world")

Im selben Ordner, in der sich unsere locustfile befindet, können wir nun folgenden Befehl ausführen:

locust -f ./path/to/locustfile.py

Hiermit wird unser erster Test gestartet, der “/hello” & “/world” GET-Requests an unseren Shop schickt, die wahrscheinlich alle einen 404-Fehler zurückgeben.

Das web Interface kann normalerweise über folgenden Link geöffnet werden: http://localhost:8089

locust main page

In dem Interface können wir die Anzahl an Besuchern, die User-Spawn-Rate in Sekunden und die URL definieren, um den Test zu starten. Nach einiger Zeit sehen wir über die Statistiken & Charts, wie sich die Ladezeiten entwickeln.

locust statistics 1
locust statistics 2

Wie ist die Locustfile aufgebaut?

Die Locustfile ist der zentrale Einstiegspunkt für unseren Lasttest. Daher ist sie besonders wichtig für uns. Genaue Infos könnt hier in der Dokumentation nachlesen. Hier eine grobe Übersicht des Aufbaus.

User-Klassen

In der Basis besteht eine Locust erstmal aus sogenannten User-Klassen. Diese erben von der aus locust importierten HttpUser-Klasse, was für die spätere Verwendung wichtig ist.

Locust erstellt aus diesen Usern später Instanzen und benutzt sie für die Ausführung von vorher definierten Aufgaben, auf die wir gleich auch noch eingehen. Eine Aufgabe kann grob z.B. sein, dass der User eine Listing-Seite aufruft und dann einen Artikel daraus öffnet.

Insgesamt brauchen wir einen User, können aber auch mehrere User anlegen, um unterschiedliche Aufgabenbereiche abzutrennen (z.B. einen User für das Surfen im Shop und einen User für das Durchführen von API-Requests wie z.B. Bestandsaktualisierungen).

Vor dem Test definieren wir ja die Gesamtanzahl der Benutzer für den Lasttest, die quasi gleichzeitig auf dem Shop sind. Im Standard wird diese Gesamtanzahl zu gleichen Teilen auf alle User-Klassen aufgeteilt. Über ein “weight”-Attribut kann aber eine Gewichtung eingebaut werden, wenn wir z.B. 10 Mal so viele normale Shop-Besucher wie API-User haben wollen.

Über das “fixed_count”-Attribut können wir auch sagen, dass wir immer eine feste Anzahl an ApiUsern haben wollen, egal wie die Gesamtanzahl der User ist. Je nach Fall kann das seine Vorteile haben.

Ein User könnte z.B. so aussehen:

from locust import HttpUser, task

class ApiUser(HttpUser):
    fixed_count = 5

    @task
    def hello_world(self):
        self.client.get("/hello")

class ShopUser(HttpUser):
    weight = 10

    @task
    def hello_world(self):
        self.client.get("/hello")

User-Tasks

In der User-Klasse können Funktionen definiert und mit einem @task versehen werden, um sie zu Task-Funktionen zu machen. Nur diese Task-Funktionen werden von locust ausgeführt. Eine task-Funktion ist im Grunde eine Aufgabe es Users, in der die konkreten Requests definiert werden. Z.B. könnte für unseren API-User ein Task so aussehen, dass ein stock-Update-Request geschickt wird und ein anderer Task so, dass ein price-Update geschickt wird.

Die taks werden von locust zufällig aufgerufen, können innerhalb eines Users aber auch gewichtet werden, damit wir z.B. 5 Mal mehr stock-Updates als Price-Updates haben wollen.

Über das “wait_time” Attribut der User-Klasse kann definiert werden, wie lange ein User zwischen zwei Tasks warten soll. Wir verwenden hier oft 2-5 Sekunden Wartezeit.

from locust import HttpUser, task

class ApiUser(HttpUser):
    fixed_count = 3

    @task(5)
    def stockUpdate(self):
        self.client.post("/stock-update")

    @task
    def priceUpdate(self):
        self.client.post("/price-update")

Wie kann ich einen Lasttest mit Locust auswerten?

Grundsätzlich ist das Erste, was wir prüfen, dass der Shop mit der Last zurechtkommt und wir uns als Kunde auch mit hoher Last im Shop ohne große Ladezeiten bewegen & Artikel kaufen können. Ist die Funktionalität des Shops weiterhin passend, ist die Basis schonmal erfüllt.

Um einen Shopware 6 Lasttest genauer zu Betrachten, müssen wir den Begriff Performance zunächst einmal genauer definieren bzw. uns verschieden Metriken anschauen, die wir hierbei messen können.

Lasttest Metriken

Bei meinen Shopware 6 Lasttest sind für mich vor allem folgende Metriken interessant:

Serverhardware

  • CPU-Auslastung/Server-Load: Zeigt, wie stark der Prozessor des Servers beansprucht wird. Hohe Auslastung kann zu Verzögerungen führen.
  • Benutzter Arbeitsspeicher (RAM): Der Teil des RAM, der von Programmen verwendet wird. Voller RAM verlangsamt den Server.
  • Disk I/O: Die Geschwindigkeit, mit der Daten von der Festplatte gelesen oder geschrieben werden. Hohe Aktivität kann die Leistung bremsen.
  • Anzahl PHP-Prozesse/Prozesse generell: Die Anzahl der laufenden Aufgaben auf dem Server. Zu viele Prozesse belasten die Leistung.
  • Netzwerk-Last: Die Menge an Daten, die über das Netzwerk fließen. Hohe Last verlangsamt den Datenverkehr.

Ladezeiten der wichtigsten Seiten

  • Durchschnittliche Ladezeit: Die durchschnittliche Zeit, die eine Seite benötigt, um komplett zu laden.
  • 95-Perzentil Ladezeit: 95 % der Ladezeiten sind schneller oder gleich dieser Zeit, nur 5 % sind langsamer. Dieser Wert ist besser als der Durchschnitt, da Ausreißer nicht berücksichtigt werden und wir ein besseres Bild für die Gesamtperformance bekommen.
  • Cache-Hit-Ratio: Der Anteil der Anfragen, die direkt aus dem Cache bedient werden, ohne den Server erneut zu belasten.
  • Throughput (Requests per Second): Die Anzahl der Anfragen, die der Server in einer Sekunde bearbeiten kann.

Vorbereitung

Bevor wir den eigentlichen Lasttest durchführen, ist es wichtig, die oben genannten Metriken mit normaler Auslastung zu sammeln. Dadurch haben wir “Soll”-Werte, an denen wir uns orientieren können.

Ratsam wäre wahrscheinlich auch auf unserem Testsystem für den Lasttest vorher einen Lasttest laufen zu lassen, der in etwa die gleiche Auslastung und damit in etwa dieselben Metriken wie der Live-Shop hat.

Wenn wir nämlich z.B. “doppelt so viele Kunden wie aktuell” testen sollen, müssen wir natürlich grob wissen, wie viele User “aktuell” grob sind, um sie entsprechend verdoppelt zu können.

Auswertungen bei Locust direkt

Die meisten Ladezeit-Metriken finden wir in den Locust-Statistiken direkt. Je nachdem, wie der Lasttest definiert ist, sehen wir hier die durchschnittliche Ladezeit, das 95-Perzentil und die Requests per Second.

locust statistics 3

Außerdem sehen wir den zeitlichen Verlauf der Werte und können so feststellen, wie sich die Metriken über einen Zeitraum entwickelt haben, was bei Problemen gewisse Erkenntnisse liefern kann.

locust statistics 4

Auswertung der Server-Metriken

Die Server-Hardware können wir nur mit Locust aktuell nicht auswerten.

Bei einem Hoster wie z.B. Maxcluster gibt es ein Monitoring-Center, bei dem man sich die einzelnen Werte anschauen und sie auch für einen bestimmten Zeitraum beobachten kann, was die Auswertung recht einfach macht.

maxcluster statistics

Hat der Hoster kein eigenes Monitoring, könnte man punktuell wahrscheinlich mit “htop” auf dem Server schauen oder mit ihm Rücksprache halten, um ein Monitoring-Tool einzubauen, das die Werte entsprechend misst.

Fazit

Shopware 6 Lasttest sind ein unverzichtbares Werkzeug, um sicherzustellen, dass Dein Shopware Shop auch unter hoher Last stabil bleibt. Mit Locust hast Du ein flexibles und effizientes Tool an der Hand, das Dir erlaubt, realistische Nutzerszenarien zu simulieren und Schwachstellen aufzudecken, bevor sie zu echten Problemen werden. So kannst Du optimal vorbereitet in den nächsten großen Sale starten!

Teste Deine Plattform regelmäßig und stelle sicher, dass Dein Shop für den nächsten Ansturm gerüstet ist 🚀

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert