Soak-Tests, die Lecks tatsächlich aufdecken: Warum achtstündige Testläufe das übersehen, was in der Produktion entdeckt wird

Soak-Tests haben ein Glaubwürdigkeitsproblem. Teams führen sie durch, erhalten einen einwandfreien Bericht, veröffentlichen den Build und stellen dann drei Tage später fest, dass in der Produktion ein Speicherleck auftritt. Der Testlauf war nicht fehlerhaft. Er hat genau das gemessen, wofür er konfiguriert war. Das Problem ist, dass die meisten Soak-Konfigurationen eine engere Fragestellung beantworten, als die Entwickler annehmen – weshalb erfolgreiche Testläufe und Speicherlecks in der Produktion weiterhin nebeneinander existieren.

In diesem Beitrag geht es darum, warum das passiert und wie man einen Lauf gestaltet, bei dem es nicht passiert. Wenn Sie in Ihrer Pipeline bereits Soak-Tests einsetzen und trotzdem Leaks ausliefern, ist die Lösung fast nie ein längerer Lauf über Nacht. Die Lösung ist eine andere Form des Tests, und sie ist Teil einer breiteren Performance-Testing-Praxis, die den Verlauf statt der Dauer zum Bestehenskriterium macht. Aktuelle Branchendaten machen die Einsätze greifbar: Eine Umfrage von New Relic beziffert die mittleren Kosten eines Betriebsausfalls auf 33.333 US-Dollar pro Minute, bei einer mittleren jährlichen Rechnung von 76 Millionen US-Dollar durch Ausfälle. Ein einzelnes Leck, das am dritten Tag auftaucht, ist ein Ergebnis-relevantes Ereignis.

Warum bestandene Soak-Tests trotzdem lecken

Die Kluft zwischen einem bestandenen Dashboard und einem Produktionsvorfall lässt sich fast immer auf einen von zwei Fehlern zurückführen. Entweder kann der Test das Leck nicht sehen, weil er nicht auf die richtige Metrik schaut, oder er kann das Leck nicht sehen, weil er den Codepfad, der leckt, überhaupt nie ausgelöst hat.

Die meisten Leitfäden beantworten das, indem sie eine Dauer vorschreiben. Acht Stunden, zwölf, zweiundsiebzig über ein Wochenende. Genau diese Vorschrift bringt Leaks in die Produktion. Ein Leck mit einer Verdopplungszeit von 40 Stunden sieht in den ersten 8 Stunden flach aus, bei 20 mäßig interessant und bei 60 erschreckend. Ein Test, der bei Stunde 8 mit einer linear aussehenden Kurve endet, ist kein Beleg für ein gesundes System. Er ist ein Beleg dafür, dass Sie zu früh aufgehört haben hinzuschauen. Der Cockroach Labs State of Resilience 2025 Report befragte 1.000 leitende Technologie-Führungskräfte und stellte fest, dass Organisationen im Durchschnitt 86 Ausfälle pro Jahr verzeichnen, wobei 70 % der Großunternehmen 60 Minuten oder länger brauchen, um jeden einzelnen zu beheben. Die meisten dieser Vorfälle wären auf der Testbank vermeidbar gewesen.

Verlauf statt Dauer

Der Rahmen ist klein, aber alles ändert sich, sobald Sie ihn akzeptieren. Ein Soak-Test besteht oder scheitert nicht anhand des Endwerts einer Metrik. Er besteht oder scheitert an der Steigung. Wenn Ihr Heap bei 2,1 GB endet, nachdem er bei 2,0 GB begann, ist die interessante Frage nicht die Differenz. Die interessante Frage ist, ob sich die Steigung des Bodenwerts nach der Garbage Collection über die letzten 60 % des Laufs statistisch von null unterscheiden lässt.

Diese Rahmung ändert, was Sie bauen. Sie hören auf zu fragen „wie lange sollte der Lauf sein“ und beginnen zu fragen „was ist das kleinste stündliche Wachstum, das ich erkennen muss, und welche Lauflänge gibt mir die Empfindlichkeit, es über dem Rauschen zu erkennen“. Sie hören auf zu fragen „sah der Graph flach aus“ und beginnen, Regressionen anzupassen. Sie hören auf, einem einzelnen Dashboard zu vertrauen, und beginnen, Heap, die Pausendauer der Garbage Collection (GC), den Höchststand des Connection-Pools und die Anzahl der File-Deskriptoren gegen dieselbe Zeitachse zu korrelieren.

Alles Folgende ist eine konkrete Ausprägung der Verlaufsrahmung. Vier blinde Flecken, vier Metriken, vier Designentscheidungen.

Soak-Tests, die Lecks tatsächlich aufdecken: Warum achtstündige Testläufe das übersehen, was in der Produktion entdeckt wird

Die vier blinden Flecken

Die meisten kurzen, gleichförmigen Läufe übersehen Leaks aus einem von vier strukturellen Gründen. Jeder hat eine diagnostische Signatur, und jeder hat eine Lösung, die nicht darin besteht, den Lauf um seiner selbst willen zu verlängern.

Zu kurz für die Verdopplungszeit

Ein Leck, das sich alle 36 Stunden verdoppelt, ist innerhalb eines 8-Stunden-Fensters nicht sichtbar. Die Kurve befindet sich in ihrer flachen, frühen exponentiellen Phase. Nach 40 Stunden im Produktivbetrieb stößt sie an ihre Grenzen. Dies ist der häufigste Grund, warum Dauertests in der Softwareprüfung genau das übersehen, wofür sie entwickelt wurden.

Das eigentliche Signal ist nicht der Rohspeicher im Heap. Dieser oszilliert mit jedem Speicherbereinigungs- und -zuweisungszyklus. Das relevante Signal ist der Heap-Floor nach der Garbage Collection, der alle 5 Minuten abgetastet und über die letzten 60 % des Laufs mittels linearer Regression analysiert wird. Ist die Steigung bei p < 0,05 größer als null, liegt ein Speicherleck vor, unabhängig davon, wie gering der absolute Wert auch erscheinen mag.

Die Lösung besteht darin, die Laufzeit anhand der Sensitivität statt nach Konvention festzulegen. Bestimmen Sie das kleinste Heap-Wachstum pro Stunde, das im Produktivbetrieb relevant wäre, und berechnen Sie dann die minimale Laufzeit, mit der Sie diese Steigung vom GC-Jitter unterscheiden können. Wenn Sie 2 MB pro Stunde innerhalb Ihres aktuellen Fensters nicht vom Rauschen unterscheiden können, ist Ihr Fenster zu kurz, und auch intensives Betrachten des Diagramms wird daran nichts ändern.

Flache Last – echter Traffic hat eine Form

Produktions-Traffic hat Spitzen und Täler. Außerhalb der Spitzenzeiten wird die Garbage Collection aggressiv, leeren sich Connection-Pools, setzt die Cache-Verdrängung ein und feuern alle daran gekoppelten Listener. Leaks, die sich bei Spitzenlast hinter GC-Druck verbergen, werden im Tal aufgedeckt. Leaks, die nur bei Cache-Verdrängung ausgelöst werden, allokieren unter einer flachen Last von 100 VU nie, weil der Cache heiß bleibt und nie etwas verdrängt wird.

Eine gleichförmige Last verdeckt außerdem die Metrik, die Sie am genauesten beobachten sollten: die Dauer und Häufigkeit der GC-Pausen über die Lastkurve hinweg, nicht den laufweiten Durchschnitt. Wonach Sie suchen, ist eine Drift der Pausendauer, die mit den Übergängen der Lastform korreliert. Durchschnittswerte verbergen die Drift; die Übergänge legen sie offen.

Die Lösung besteht darin, den Soak so zu formen, dass er Ihrer tatsächlichen Traffic-Kurve entspricht. Hochfahren, ein paar Stunden auf Spitzenlast halten, für 90 Minuten auf 20 % absenken, wieder hochfahren. Wiederholen Sie den Zyklus über den gesamten Lauf. Wenn Ihre Produktion eine nächtliche Ruhestunde hat, bauen Sie eine Ruhestunde in den Test ein. Eine flache Linie auf dem Lastgenerator ist ein Lasttest mit Soak-Länge-Ambitionen, kein echter Soak.

Der geplante Job, den Sie vergessen haben auszuführen

Die Codepfade, die am ehesten lecken, sind diejenigen, die selten laufen: Cron-Jobs, mitternächtlicher Abgleich, wöchentliche Berichtserstellung, stündliches Kafka-Rebalancing, nächtliches Datenbank-Vacuum. Sie werden seltener überprüft, sie allokieren große transiente Strukturen und halten Referenzen länger, als sie sollten. Und sie tauchen fast nie im Soak-Szenario auf, das typischerweise nur den HTTP-Request-Fluss abdeckt.

Hier sind die Metriken, die man auf der Zeitachse überlagern sollte, eher Sprungfunktionen als Steigungen:

  • Der Höchststand des Connection-Pools wird rund um jede Ausführung eines geplanten Jobs erfasst.
  • Die Anzahl der File-Deskriptoren vor, während und nach dem Job.
  • Die Thread-Anzahl, falls der Job Worker erzeugt.
  • Jede Warteschlangentiefe, die der Job erzeugt oder verbraucht.

Wenn eine davon bei jeder Job-Ausführung nach oben klettert und nie wieder zurückkommt, haben Sie ein Leck gefunden, das ein reiner Traffic-Lauf nie aufgedeckt hätte.

Die Design-Lösung ist eine Änderung der Definition. Ihr Szenario ist nicht „Traffic“. Es ist „Traffic plus Kalender“. Zählen Sie jeden geplanten Job auf, der während einer Produktionswoche feuern würde, und komprimieren Sie entweder seinen Zeitplan in das Testfenster oder lösen Sie ihn explizit in realistischen Abständen aus. Ein Lauf, der nie einen vollständigen Zyklus Ihres langsamsten geplanten Jobs ausführt, ist ein Lastlauf mit Soak-Länge-Ambitionen.

Nicht übereinstimmende Neustart-Richtlinie

Dies ist der subtilste und der am häufigsten übersehene Punkt. Testumgebungen werden aggressiv recycelt. CI startet pro Lauf einen frischen Container. Der Orchestrator killt alles mit einem 5xx-Spike. Health-Check-Schwellenwerte sind eng auf schnelles Feedback abgestimmt. Die Produktion hingegen läuft möglicherweise 30 Tage lang zwischen Neustarts. Ein Leck, das 200 Stunden bräuchte, um relevant zu werden, bekommt in einem Test, der bei Stunde 12 zurückgesetzt wird, weil ein Health-Check ausschlug, nie die Chance, relevant zu werden.

Die zu beobachtende Metrik ist trivial: die Uptime des Containers oder Prozesses neben der Leck-Metrik. Jeder Neustart während des Laufs macht den Verlauf ab diesem Punkt ungültig. Dennoch wird diese Korrelation in den meisten CI-Setups nie geplottet, und der Lauf wird als grün markiert, weil die Metriken nach dem Neustart zufällig in Ordnung aussahen.

Die Lösung besteht darin, in der Testumgebung die Neustart-Richtlinie der Produktion abzubilden, nicht die von CI. Erweitern Sie die Liveness-Schwellenwerte. Deaktivieren Sie für die Dauer des Laufs das aggressive Killen durch Health-Checks. Behandeln Sie jeden Neustart mitten im Lauf als fehlgeschlagenen Soak-Test, der eine Untersuchung und einen erneuten Lauf erfordert, statt als kleinen Aussetzer, den Sie im Dashboard übergehen. Wenn Ihr Orchestrator in der Produktion einen 30-Tage-Prozess tolerieren würde, sollte Ihre Testbank einen für die Dauer des Laufs tolerieren.

Wie ein echter Soak-Test aussieht

Verwenden Sie dies als Prüfliste für Ihren nächsten Lauf. Wenn Ihre aktuelle Pipeline bei mehr als drei davon scheitert, ist die Acht-Stunden-Zahl nicht Ihr Problem.

  • Die Lauflänge wird durch die angestrebte Erkennungsempfindlichkeit festgelegt, berechnet aus dem akzeptablen stündlichen Wachstum, und nicht durch „über Nacht“
  • Die Lastkurve ist so geformt, dass sie die Produktion widerspiegelt, mit Spitzen, Tälern und Übergängen, statt eines flachen Plateaus
  • Jeder geplante Job, der in einer Produktionswoche feuern würde, wird entweder in das Laufzeitfenster komprimiert oder explizit ausgelöst
  • Die Neustart- und Liveness-Richtlinie in der Testumgebung entspricht der Produktion, nicht den CI-Standardwerten
  • Der Heap-Bodenwert nach der GC ist das primäre Heap-Signal, nicht der rohe Heap, und er wird mit einer linearen Regression über die letzten 60 % des Laufs angepasst
  • Der Höchststand des Connection-Pools, die Anzahl der File-Deskriptoren und die Thread-Anzahl werden als Zeitreihen mit derselben Achse wie die Last und der Job-Zeitplan geplottet
  • Die GC-Pausendauer wird über die Lastkurve hinweg verfolgt, nicht als laufweiter Durchschnitt zusammengefasst
  • Jeder Prozess-Neustart mitten im Lauf macht den Lauf automatisch ungültig und erfordert eine Untersuchung, bevor er als grün markiert werden kann
  • Das Bestehenskriterium ist als Steigungsschwelle und Höchststand-Obergrenze formuliert, nicht als „der Graph sah flach aus“

Verfehlen Sie auch nur einen davon, haben Sie einen Lauf gebaut, der ein falsches Grün erzeugen kann. Erfüllen Sie alle neun, und die Läufe, die bestehen, werden etwas bedeuten.

Wo Soak-Testing in den Rest passt

Sustained-Load-Testing beantwortet eine Frage: was sich im Laufe der Zeit ansammelt. Es ersetzt die anderen Performance-Disziplinen nicht, und es hängt von ihnen ab. Lasttests sagen Ihnen, ob das System den Spitzendurchsatz hält; ohne diese Basislinie hat ein geformter Soak keine Ziellast, die er halten könnte. Das Burst-Verhalten ist eine völlig eigene Frage, und wenn Sie das System nicht mit plötzlichem Traffic gestresst haben, liefern Sie blind in jeden Marketing-Launch, jedes virale Ereignis und jeden Montagmorgen-Login-Ansturm.

Verteilte Architekturen fügen ihre eigene Dimension hinzu. Ein Monolith leckt in einem Prozess; ein Geflecht von Services kann in der Art lecken, wie sie miteinander kommunizieren, und der Trace muss der Anfrage über jeden Hop folgen. Sustained-Load-Läufe über Microservices hinweg mit Korrelation verteilter Traces durchzuführen, ist eine andere Disziplin, als einen einzelnen Service zu soaken, und verdient ein eigenes Szenariodesign. Dasselbe gilt eine Ebene tiefer an der Schnittstelle: Die Engpässe auf API-Ebene, die unter Dauerlast auftauchen, verstärken jeden Fehlermodus in den vier blinden Flecken oben, denn ein langsamer Vertrag potenziert jedes Leck, das die Arbeitslast auslöst.

Auf Erkennungsempfindlichkeit auslegen

Die Acht-Stunden-Zahl ist ein Sicherheitstuch. Was zählt, ist, ob Ihr Lauf die Steigung in den Metriken sehen kann, die lecken: Heap-Bodenwert nach der GC, Pool-Tiefe, Anzahl der File-Deskriptoren, GC-Pausendauer – über Lastformen und geplante Jobs hinweg, die widerspiegeln, was die Produktion tatsächlich tut. Legen Sie auf Erkennungsempfindlichkeit aus. Wenn Ihr letzter Lauf bestanden hat und die Produktion trotzdem leckte, muss der nächste nicht länger sein. Er muss das Richtige betrachten, in der richtigen Form, mit der richtigen Neustart-Richtlinie. Wenn Sie bereit sind, einen zu bauen, der das Leck wirklich findet, kontaktieren Sie uns, und wir gestalten ihn gemeinsam mit Ihnen.

FAQ

Wie lange sollte ein Soak-Test laufen?

Lang genug, um das kleinste stündliche Ressourcenwachstum, das in der Produktion von Bedeutung wäre, vom Jitter der Garbage Collection zu unterscheiden. Wenn eine Heap-Steigung von 2 MB pro Stunde Ihren Service innerhalb einer Woche Uptime lahmlegen würde, muss Ihr Lauf lang genug sein, um diese Steigung mit einer linearen Regression auf dem Bodenwert nach der GC über dem Rauschen zu erkennen. Das ist in der Regel länger als 8 Stunden und oft kürzer als 72.

Was ist der Unterschied zwischen Soak-Testing und Endurance-Testing?

Es ist dieselbe Praxis unter zwei Namen. Manche Teams und Anbieter bevorzugen „Endurance“, andere „Soak“; die Meinungsverschiedenheit ist regional und stilistisch, nicht technisch. Beides bedeutet Dauerlast über einen längeren Zeitraum, wobei man auf Ansammlung achtet.

Warum hat mein Soak-Test bestanden, aber die Produktion hatte ein Speicherleck?

Fast immer einer von vier Gründen: Der Lauf war kürzer als die Verdopplungszeit des Lecks, die Last war flach, während die Produktion eine tageszeitliche Form hat, der Lauf hat nie einen geplanten Job ausgeführt, der leckt, oder die Testumgebung hat einen Prozess neu gestartet, den der Orchestrator in der Produktion am Leben gehalten hätte. Beheben Sie das Design, nicht die Dauer.

Sehen Sie, wie QAwerk 8 inhaltsreiche Portale unter Dauer-Traffic von 110 Millionen Studierenden pro Jahr stabil hielt, bevor Keystone weiter skalierte.

Bitte geben Sie Ihre Geschäfts-E-Mail ein ist keine Geschäfts-E-Mail