Warum manche Probleme erst nach Stunden oder Tagen kontinuierlicher Last sichtbar werden und wie Soak-Tests genau diese Klasse von Fehlern gezielt aufdeckt
Ein Lasttest, der über fünf Minuten eine hohe Anzahl gleichzeitiger Nutzer simuliert, bestätigt lediglich, dass ein System kurzfristig mit dieser Last umgehen kann, sagt aber nichts darüber aus, was passiert, wenn dieselbe, moderate Last über zwölf oder vierundzwanzig Stunden ununterbrochen anhält. Genau diese Frage beantwortet ein Soak-Test (auch Endurance-Test genannt), der eine realistische, aber konstante Last über einen deutlich längeren Zeitraum aufrechterhält, um schleichende Probleme wie Speicherlecks, langsam erschöpfte Ressourcen-Pools oder unkontrolliert wachsende Log-Dateien aufzudecken, bevor sie in Produktion nach Stunden stabilen Betriebs plötzlich zuschlagen.
Inhaltsverzeichnis
- 1. Warum kurze Lasttests bestimmte Probleme systematisch übersehen
- 2. Memory Leaks systematisch aufspüren
- 3. Connection-Pool-Erschöpfung erkennen
- 4. Log-Wachstum und Festplattenverbrauch überwachen
- 5. Typische Laufzeiten und Lastintensität für Soak-Tests
- 6. Unterschied zu kurzen Last-Spitzentests
- 7. Automatisiertes Monitoring und Alarmierung während des Soak-Tests
- 8. Soak-Tests sinnvoll in die CI/CD-Pipeline einplanen
- 9. Soak-Test-Erkenntnisziele im Überblick
- 10. Zusammenfassung
- 11. FAQ
1. Warum kurze Lasttests bestimmte Probleme systematisch übersehen
Ein klassischer Lasttest mit k6 oder ähnlichen Werkzeugen läuft typischerweise wenige Minuten bis maximal eine Stunde und beantwortet damit zuverlässig die Frage, ob ein System eine bestimmte Anzahl gleichzeitiger Nutzer kurzfristig bewältigt. Bestimmte Fehlerklassen entstehen aber erst durch die kumulative Wirkung über lange Zeiträume und bleiben in einem kurzen Testlauf grundsätzlich unsichtbar, selbst bei identischer Lastintensität.
Ein Speicherleck, bei dem jede einzelne Anfrage nur wenige Kilobyte nicht korrekt freigegebenen Speicher hinterlässt, fällt bei tausend Anfragen über fünf Minuten noch nicht ins Gewicht, summiert sich aber über Millionen Anfragen an einem einzigen Tag zu einem Speicherverbrauch, der den verfügbaren Arbeitsspeicher eines PHP-FPM-Worker-Prozesses irgendwann tatsächlich sprengt und zu einem harten Absturz oder einem vom Betriebssystem erzwungenen Neustart des Prozesses führt.
Soak-Tests schließen diese Erkennungslücke, indem sie eine moderate, realistische Last bewusst über Stunden oder sogar Tage aufrechterhalten, wodurch sich kumulative Effekte, die bei kurzen Testläufen unter der Wahrnehmungsschwelle bleiben, über die Zeit zu einem klar messbaren, eindeutig erkennbaren Trend aufsummieren.
2. Memory Leaks systematisch aufspüren
Der klassischste und wirtschaftlich teuerste Anwendungsfall für Soak-Tests ist das Aufspüren von Speicherlecks, bei denen ein Prozess über die Zeit kontinuierlich mehr Arbeitsspeicher belegt, ohne ihn bei abgeschlossenen Anfragen wieder vollständig freizugeben. In PHP-Anwendungen entstehen solche Lecks häufig durch statische Klassenvariablen, die über mehrere Requests hinweg unbeabsichtigt Daten akkumulieren, durch nicht korrekt geschlossene Datei-Handles, oder durch Event-Listener, die bei jeder Anfrage neu registriert, aber nie wieder entfernt werden.
Während eines Soak-Tests wird der Speicherverbrauch der relevanten Prozesse kontinuierlich über die gesamte Testlaufzeit aufgezeichnet, typischerweise per Monitoring-Werkzeug wie Prometheus mit einem Grafana-Dashboard. Ein Prozess mit gesundem Speicherverhalten zeigt dabei nach einer anfänglichen Einschwingphase einen weitgehend konstanten, sägezahnartigen Verlauf durch reguläre Garbage Collection, während ein Prozess mit einem echten Leck einen stetig, meist annähernd linear ansteigenden Trend zeigt, der ohne Eingriff früher oder später zwangsläufig in einem Speicher-Erschöpfungsfehler endet.
# Speicherverbrauch der PHP-FPM-Worker während eines Soak-Tests
# in regelmäßigen Intervallen protokollieren
while true; do
echo "$(date +%s) $(ps -eo rss,cmd | grep 'php-fpm: pool' | \
awk '{sum+=$1} END {print sum}')" >> soak-memory.log
sleep 60
done
# anschließend den Trend visuell prüfen, etwa mit gnuplot
# oder die Rohdaten in Prometheus/Grafana importieren
3. Connection-Pool-Erschöpfung erkennen
Ein weiteres, typisches Soak-Test-Problem ist die schleichende Erschöpfung von Datenbank- oder Redis-Connection-Pools, bei der einzelne Verbindungen nach Abschluss einer Anfrage nicht korrekt an den Pool zurückgegeben werden, etwa weil eine unbehandelte Exception den regulären Aufräum-Code umgeht. Bei niedriger Last fällt eine einzelne, verwaiste Verbindung praktisch nicht auf, da der Pool über genügend freie Verbindungen verfügt, doch über Stunden hinweg summieren sich diese verwaisten Verbindungen, bis der Pool vollständig erschöpft ist und neue Anfragen mit einem Verbindungsfehler fehlschlagen, obwohl die Datenbank selbst völlig normal arbeitet.
Dieses Muster ist besonders tückisch, weil die Fehlermeldung, die letztlich in Produktion auftritt, meist nicht auf die eigentliche Ursache hinweist: Ein "Connection Pool erschöpft"-Fehler nach zwölf Stunden stabilen Betriebs sieht auf den ersten Blick nach einem plötzlichen, unerklärlichen Vorfall aus, ist aber tatsächlich das vorhersehbare Endergebnis einer über Stunden schleichend akkumulierten Ressourcen-Verletzung, die ein Soak-Test gezielt und reproduzierbar vorab sichtbar macht.
4. Log-Wachstum und Festplattenverbrauch überwachen
Neben Arbeitsspeicher und Verbindungen ist unkontrolliertes Log-Wachstum ein drittes, häufig unterschätztes Soak-Test-Erkenntnisziel: Eine Anwendung, die bei jeder Anfrage eine zusätzliche, eigentlich für das Debugging gedachte Log-Zeile schreibt, erzeugt bei niedriger Last kein spürbares Problem, kann aber bei kontinuierlicher Produktionslast über einen Tag mehrere Gigabyte an Log-Daten produzieren, die schließlich die verfügbare Festplattenkapazität erschöpfen und damit den gesamten Server, nicht nur die Anwendung selbst, funktionsunfähig machen.
Ein Soak-Test sollte deshalb neben Speicher- und Verbindungs-Metriken auch das Wachstum relevanter Log-Verzeichnisse (etwa `var/log` in einer Magento-Installation) über die gesamte Testlaufzeit erfassen, um ein realistisches Bild des tatsächlichen Ressourcenverbrauchs unter Dauerlast zu erhalten, statt diesen Aspekt komplett auszublenden.
5. Typische Laufzeiten und Lastintensität für Soak-Tests
Während ein regulärer Lasttest auf hohe, aber kurzzeitige Belastung ausgelegt ist, zielt ein Soak-Test bewusst auf eine moderate, realistische Alltagslast über einen deutlich längeren Zeitraum, typischerweise zwischen acht und vierundzwanzig Stunden, in kritischen Fällen auch mehrere Tage am Stück. Die Lastintensität selbst orientiert sich dabei meist an der tatsächlich beobachteten, durchschnittlichen Produktionslast, nicht an einem künstlichen Maximalwert, da das Ziel nicht das Erreichen einer Belastungsgrenze ist, sondern das Aufdecken von Effekten, die sich erst über Zeit akkumulieren.
Für einen Magento-Shop bietet sich beispielsweise ein Soak-Test mit einer konstanten, moderaten Anzahl gleichzeitiger virtueller Nutzer an, die realistische Kataloganfragen, Warenkorb-Aktionen und gelegentliche Checkouts über vierundzwanzig Stunden hinweg durchführen, während Speicher-, Verbindungs- und Log-Metriken parallel kontinuierlich aufgezeichnet werden.
6. Unterschied zu kurzen Last-Spitzentests
Ein Spike-Test (siehe den separaten Artikel zu diesem Thema) und ein Soak-Test verfolgen bewusst gegensätzliche Ziele: Ein Spike-Test prüft, wie ein System auf eine plötzliche, kurzzeitige, extreme Lasterhöhung reagiert, während ein Soak-Test bewusst auf konstante, moderate Last über lange Zeit setzt, um kumulative statt momentane Effekte aufzudecken. Beide Testarten ergänzen sich, decken aber grundlegend unterschiedliche Fehlerklassen ab und ersetzen einander deshalb nicht.
Ein System, das einen Spike-Test problemlos übersteht, kann trotzdem an einem Soak-Test scheitern, wenn es zwar kurzzeitige Lastspitzen korrekt abfängt, aber über Stunden hinweg langsam Ressourcen verliert, ein wichtiger Grund, warum ein vollständiges Test-Portfolio idealerweise beide Testarten kombiniert, statt sich auf eine einzelne zu beschränken.
7. Automatisiertes Monitoring und Alarmierung während des Soak-Tests
Da ein Soak-Test über Stunden oder Tage läuft, ist eine manuelle, ständige Beobachtung der Kennzahlen weder praktikabel noch sinnvoll. Stattdessen sollte ein Soak-Test von Beginn an mit automatisierten Alarmschwellen ausgestattet sein, die das verantwortliche Team benachrichtigen, sobald eine überwachte Kennzahl, etwa der Speicherverbrauch oder die Anzahl offener Datenbankverbindungen, einen definierten Grenzwert überschreitet, statt das Ergebnis erst nach vollständigem Testablauf manuell auszuwerten.
Diese Alarmierung erlaubt es zusätzlich, ein Problem bereits während des laufenden Tests näher zu untersuchen, etwa durch das gezielte Ziehen eines Speicherabbilds (Heap-Dump) genau in dem Moment, in dem der Speicherverbrauch beginnt, deutlich vom erwarteten Verlauf abzuweichen, was die anschließende Fehlersuche erheblich erleichtert im Vergleich zu einer nachträglichen Analyse ohne konkreten Zeitpunkt der Abweichung.
8. Soak-Tests sinnvoll in die CI/CD-Pipeline einplanen
Ein Soak-Test mit einer Laufzeit von vierundzwanzig Stunden passt naturgemäß nicht in einen regulären Pull-Request-Workflow, der auf schnelles Feedback binnen weniger Minuten ausgelegt ist. Stattdessen etabliert sich in der Praxis ein zeitlich entkoppelter Ansatz: Ein Soak-Test startet automatisiert, etwa über einen nächtlichen oder wöchentlichen geplanten CI-Job, gegen eine dedizierte, produktionsnahe Staging-Umgebung, während die reguläre Entwicklungsarbeit im Hauptzweig unabhängig davon weiterläuft.
Wichtig ist dabei, dass die Ergebnisse eines Soak-Tests nicht in einem isolierten Log verschwinden, sondern aktiv an das verantwortliche Team kommuniziert werden, etwa über eine automatisierte Zusammenfassung in einem Team-Chat-Kanal nach Abschluss des Testlaufs, da ein Soak-Test, dessen Ergebnis niemand tatsächlich ansieht, seinen Zweck vollständig verfehlt, unabhängig davon, wie technisch sauber er konfiguriert wurde.
9. Soak-Test-Erkenntnisziele im Überblick
Die folgende Tabelle fasst die wichtigsten Erkenntnisziele eines Soak-Tests zusammen.
| Erkenntnisziel | Typisches Symptom | Beobachtungsmethode |
|---|---|---|
| Memory Leak | Stetig steigender Speicherverbrauch | Kontinuierliches Prozess-Monitoring |
| Connection-Pool-Erschöpfung | Verbindungsfehler nach Stunden stabilen Betriebs | Pool-Auslastung über Zeit tracken |
| Log-Wachstum | Sinkende Festplattenkapazität | Verzeichnisgröße periodisch messen |
| Langsame Ressourcen-Degradation | Antwortzeiten steigen ohne Lasterhöhung | Antwortzeit-Trend über Testdauer vergleichen |
Mironsoft
E2E-Teststrategie, CI-Integration und stabile Testsuiten
Testsuiten, die Bugs finden statt nur rot zu blinken?
Wir prüfen bestehende E2E-Testsuiten auf Flakiness, fehlende Testisolation und ineffiziente CI-Laufzeiten und bauen daraus eine Teststrategie, die tatsächlich Vertrauen schafft statt nur Haken zu setzen.
Test-Audit
Flaky Tests, Testpyramide und Coverage-Lücken systematisch aufdecken.
CI-Optimierung
Parallele Ausführung, Retry-Strategien und schnelle Feedback-Zyklen aufbauen.
Cypress/Playwright-Setup
Robuste E2E-Suiten für Magento-Frontends von Grund auf einrichten.
10. Zusammenfassung
Soak-Tests: Das Wichtigste auf einen Blick
Kernidee
Moderate, realistische Last über Stunden oder Tage aufrechterhalten, um kumulative Effekte sichtbar zu machen.
Wichtigster Fund
Memory Leaks, die bei kurzen Lasttests unter der Wahrnehmungsschwelle bleiben.
Typische Laufzeit
Acht bis vierundzwanzig Stunden, in kritischen Fällen auch mehrere Tage am Stück.
Abgrenzung
Spike-Tests prüfen kurzzeitige Extremlast, Soak-Tests prüfen kumulative Effekte über Zeit.