Soak testing heeft een geloofwaardigheidsprobleem. Teams voeren het uit, krijgen een schoon rapport, releasen de build en zien drie dagen later een geheugenlek ontstaan in de productieomgeving. De test was niet stuk. Er werd gemeten wat geconfigureerd was om te meten. Het probleem is dat de meeste soak-configuraties een veel beperktere vraag beantwoorden dan engineers denken, en daarom blijven succesvolle tests en lekkende productieomgevingen naast elkaar bestaan.
Dit artikel gaat over waarom dat gebeurt en hoe u een test ontwerpt die dit niet heeft. Als u al soak testing in uw pipeline gebruikt en er toch lekken doorkomen, is de oplossing bijna nooit een langere run ‘s nachts. De oplossing is een ander type test, onderdeel van een bredere performance testing-strategie die de trend (trajectory) als succescriterium beschouwt in plaats van de duur. Recente data uit de sector maken de belangen concreet: het onderzoek van New Relic stelt de mediane kosten van een operationele onderbreking vast op $33.333 per minuut, met een gemiddelde jaarlijkse rekening van $76 miljoen door uitval. Eén enkel lek dat op dag drie opduikt, is een directe aanslag op de winst-en-verliesrekening.
Waarom succesvolle soak-tests toch lekken
Het gat tussen een positief dashboard en een productie-incident is bijna altijd terug te voeren op een van de twee volgende fouten. Ofwel de test ziet het lek niet omdat de verkeerde metriek wordt gevolgd, of de test ziet het lek niet omdat het nooit het codepad heeft getriggerd dat daadwerkelijk lekt.
De meeste handleidingen beantwoorden dit door een tijdsduur voor te schrijven. Acht uur, twaalf, tweeënzeventig uur over het weekend. Dat voorschrift zorgt ervoor dat lekken de productieomgeving bereiken. Een lek met een verdubbelingstijd van 40 uur ziet er de eerste 8 uur vlak uit, is na 20 uur licht interessant en na 60 uur angstaanjagend. Een test die na 8 uur stopt met een lineair ogende curve is geen bewijs van een gezond systeem. Het is bewijs dat u te vroeg bent gestopt met kijken. Het rapport State of Resilience 2025 van Cockroach Labs ondervroeg 1.000 senior technologie-executives en ontdekte dat organisaties gemiddeld 86 uitvalmomenten per jaar hebben, waarbij het bij 70% van de grote ondernemingen 60 minuten of langer duurt om elk incident op te lossen. De meeste van deze incidenten waren bij de testopstelling te voorkomen geweest.
Trend boven duur
Het kader is klein, maar alles verandert als u dit accepteert. Een soak-test slaagt of faalt niet op basis van de eindwaarde van een metriek. Het slaagt of faalt op basis van de hellingsgraad (slope). Als uw heap na een start van 2,0 GB eindigt op 2,1 GB, is de interessante vraag niet de delta. De interessante vraag is of de hellingsgraad van de vloer na de garbage collection statistisch gezien afwijkt van nul over de laatste 60% van de run.
Die insteek verandert wat u bouwt. U stopt met de vraag “hoe lang moet de run zijn” en begint met de vraag “wat is de kleinste groei per uur die ik moet detecteren en welke run-lengte geeft me de gevoeligheid om dit boven de ruis uit te detecteren.” U stopt met vertrouwen op een vlakke grafiek en begint regressies toe te passen. U stopt met het vertrouwen op één dashboard en begint heap, GC-pauzeduur, het maximumgebruik van de connection pool en het aantal file descriptors tegen dezelfde tijdsas af te zetten.
Alles hieronder is een specifieke manier waarop de trend-insteek werkt. Vier blinde vlekken, vier metrieken, vier ontwerpkeuzes.
De vier blinde vlekken
De meeste korte, uniforme runs missen lekken door een van de vier structurele redenen. Elke reden heeft een diagnostisch kenmerk en elke reden heeft een oplossing waarvoor de run niet om de duur zelf verlengd hoeft te worden.
Te kort voor de verdubbelingstijd
Een lek dat elke 36 uur verdubbelt, is onzichtbaar binnen een venster van 8 uur. De curve bevindt zich in de vlakke, vroeg-exponentiële zone. Tegen uur 40 in productie is het een muur. Dit is de meest voorkomende reden dat soak testing in software-testen mist wat het juist moest vangen.
Het signaal dat u werkelijk wilt, is niet de ruwe heap. De ruwe heap oscilleert bij elke allocatie- en collectiecyclus. Het signaal is de heap-vloer na de GC, elke 5 minuten gesampled, met een lineaire regressie toegepast over de laatste 60% van de run. Als de hellingsgraad groter is dan nul bij p < 0,05, dan is er sprake van een lek, hoe bescheiden het absolute getal er ook uitziet.
De ontwerpmatige oplossing is om de lengte van uw run in te stellen op basis van gevoeligheid in plaats van conventie. Bepaal de kleinste heap-groei per uur die relevant zou zijn in productie en bereken vervolgens de minimale run-lengte die u in staat stelt om die hellingsgraad te onderscheiden van GC-jitter. Als u binnen uw huidige venster 2 MB per uur niet kunt onderscheiden van ruis, is uw venster te kort en lost turen naar de grafiek niets op.
Vlakke belasting versus verkeer met een patroon
Productieverkeer heeft pieken en dalen. Buiten piekuren wordt de garbage collection agressiever, lopen connection pools leeg en vindt cache-evictie plaats, wat alle listeners activeert die daaraan gekoppeld zijn. Lekken die zich bij piekbelasting achter de GC-druk verschuilen, komen tijdens daluren bloot te liggen. Lekken die alleen door cache-evictie worden veroorzaakt, alloceren nooit onder een vlakke belasting van 100 VU, omdat de cache warm blijft en er niets wordt geëvicte.
Een uniforme belasting maskeert ook de metriek die u het nauwst in de gaten moet houden: de duur en frequentie van de GC-pauze over de belastingcurve, niet het gemiddelde over de hele run. Waar u naar zoekt is drift in de pauzeduur die correleert met overgangen in het belastingpatroon. Gemiddelden verhullen de drift; de overgangen leggen deze bloot.
De oplossing is om de soak-test vorm te geven naar uw werkelijke verkeerscurve. Schaal op, houd de piek een paar uur vast, zak naar 20% voor 90 minuten, schaal weer op. Herhaal de cyclus gedurende de run. Als uw productieomgeving een nachtelijk stil uur heeft, verwerk dan een stil uur in de test. Een vlakke lijn op de load generator is een belastingtest met de ambitie van een soak-test, geen echte soak-test.
De geplande taak die u vergat uit te voeren
De codepaden die het meest waarschijnlijk lekken, zijn de paden die zelden draaien: cron jobs, reconciliatie om middernacht, genereren van wekelijkse rapporten, elk uur Kafka-rebalancing, nachtelijke database-vacuum. Ze krijgen minder reviews, alloceren grote tijdelijke structuren en houden referenties langer vast dan zou moeten. En ze verschijnen bijna nooit in het soak-scenario, dat doorgaans alleen de HTTP-requestflow dekt.
Hierbij zijn de metrieken die u op de tijdlijn moet leggen trapfuncties in plaats van hellingen:
- Maximumgebruik van de connection pool, gesampled rondom elke uitvoering van een geplande taak.
- Aantal file descriptors voor, tijdens en na de taak.
- Aantal threads als de taak workers start.
- Elke queue-diepte die de taak produceert of verbruikt.
Als een van deze waarden bij elke uitvoering van de taak omhoog gaat en nooit meer terugkeert naar het oude niveau, heeft u een lek gevonden dat een test met alleen verkeer nooit aan het licht zou brengen.
De ontwerpmatige oplossing is een verandering van definitie. Uw scenario is niet “verkeer”, het is “verkeer plus de kalender”. Inventariseer elke geplande taak die in een productieweek zou draaien en comprimeer ofwel het schema in het testvenster, of trigger ze expliciet met realistische tussenpozen. Een run die nooit een volledige cyclus van uw traagste geplande taak uitvoert, is een belastingrun met de ambitie van een soak-test.
Mismatch in restart-beleid
Dit is het subtielste punt en het punt dat het vaakst over het hoofd wordt gezien. Testomgevingen worden agressief ververst. CI start bij elke run een nieuwe container. De orchestrator beëindigt alles met een 5xx-piek. Drempelwaarden voor health-checks zijn scherp afgesteld voor snelle feedback. Productieomgevingen kunnen daarentegen wel 30 dagen draaien tussen herstarts door. Een lek dat 200 uur nodig zou hebben om relevant te worden, krijgt nooit de kans om dat te worden in een test die na 12 uur opnieuw opstart omdat een health-check flapperde.
De metriek om in de gaten te houden is eenvoudig: container- of proces-uptime in combinatie met de lek-metriek. Elke herstart tijdens de run maakt het verloop vanaf dat moment ongeldig. Toch wordt in de meeste CI-opstellingen deze correlatie nooit in kaart gebracht en wordt de run als geslaagd gemarkeerd omdat de metrieken na de herstart toevallig in orde leken.
De oplossing is om in de testomgeving hetzelfde herstartbeleid te hanteren als in productie, en niet dat van CI. Verruim de liveness-drempelwaarden. Schakel agressieve health-check-beëindigingen uit voor de duur van de run. Beschouw elke herstart halverwege een run als een mislukte soak-test die onderzoek en een nieuwe run vereist, in plaats van als een klein ongemak waar u in het dashboard aan voorbijgaat. Als uw orchestrator een 30-dagenproces in productie zou tolereren, zou uw testomgeving dat ook moeten doen voor de gehele duur van de run.
Hoe een echte soak-test eruitziet
Gebruik dit als checklist voor uw volgende run. Als uw huidige pipeline op meer dan drie van deze punten faalt, is die acht uur niet uw eigenlijke probleem.
- De looptijd wordt bepaald door de detectiegevoeligheid, berekend op basis van aanvaardbare groei per uur, niet op basis van “een nachtje draaien”
- De belastingscurve is zo gevormd dat deze de productie spiegelt, met pieken, dalen en overgangen, in plaats van een vlak plateau
- Elke geplande taak die in een productieweek zou draaien, is ofwel gecomprimeerd in het run-venster of expliciet getriggerd
- Het herstart- en liveness-beleid in de testomgeving komt overeen met dat van productie, niet met de CI-standaardinstellingen
- De post-GC heap-bodem is het primaire heap-signaal, niet de ruwe heap, en deze is voorzien van een lineaire regressie over de laatste 60% van de run
- De bovengrens van de connection pool, het aantal bestandsdescriptors en het aantal threads worden weergegeven als tijdreeksen met dezelfde as als de belasting en het taakschema
- De duur van de GC-pauze wordt gevolgd over de belastingscurve, niet samengevat als een gemiddelde over de hele run
- Elke herstart van een proces halverwege de run maakt de run automatisch ongeldig en vereist onderzoek voordat deze als geslaagd kan worden gemarkeerd
- Het slaagcriterium is geformuleerd als een hellingsdrempel en een bovengrens, niet als “de grafiek zag er vlak uit”
Mist u een van deze punten, dan hebt u een run gebouwd die een vals-positief resultaat kan geven. Als u alle negen punten afvinkt, hebben de runs die slagen ook echt betekenis.
Waar soak-testen in het geheel passen
Sustained-load testen beantwoordt één vraag: wat hoopt zich op in de loop van de tijd? Het vervangt niet de andere performancedisciplines en is ervan afhankelijk. Load-testen vertellen u of het systeem piekbelasting aankan; zonder die basislijn heeft een soak-test met een specifieke vorm geen doelbelasting om vast te houden. Burst-gedrag is een compleet andere kwestie, en als u het systeem niet hebt gestrest met plotselinge verkeerstoenames, gaat u blind elke marketinglancering, virale gebeurtenis of maandagochtend-inlogpiek tegemoet.
Gedistribueerde architecturen voegen een eigen dimensie toe. Een monolith lekt in één proces; een netwerk van services kan lekken op de manier waarop ze met elkaar communiceren, en de trace moet het verzoek volgen via elke hop. Het uitvoeren van sustained-load runs op microservices met gecorreleerde gedistribueerde traces is een andere discipline dan het testen van een enkele service, en het verdient zijn eigen scenario-ontwerp. Hetzelfde geldt een laag lager op het interface-niveau: de API-bottlenecks die onder duurzame belasting verschijnen, versterken elk faalmechanisme in de vier blinde vlekken hierboven, omdat een traag contract elk lek dat de workload veroorzaakt, verergert.
Ontwerp voor detectiegevoeligheid
Die acht uur is slechts een geruststellende gedachte. Waar het om gaat is of uw run in staat is om een stijgende lijn te zien in de metrieken die lekken: de post-GC heap-bodem, pool-diepte, het aantal bestandsdescriptors, de duur van de GC-pauze, over belastingsvormen en geplande taken die de werkelijke productieomgeving spiegelen. Ontwerp voor detectiegevoeligheid. Als uw vorige run slaagde en de productie toch lekte, hoeft de volgende niet langer te duren. Hij moet naar de juiste zaken kijken, in de juiste vorm en met het juiste herstartbeleid. Wanneer u klaar bent om een test te bouwen die het lek daadwerkelijk vindt, neem contact met ons op en wij ontwerpen deze samen met u.
Veelgestelde vragen
Hoe lang moet een soak-test duren?
Lang genoeg om de kleinste resourcegroei per uur die in productie relevant zou zijn, te onderscheiden van garbage-collection jitter. Als een heap-stijging van 2 MB per uur uw service in een week uptime zou laten crashen, moet uw run lang genoeg zijn om die stijging boven de ruis uit te detecteren met een lineaire regressie op de post-GC-bodem. Dat is meestal langer dan 8 uur en vaak korter dan 72.
Wat is het verschil tussen soak-testen en endurance-testen?
Dit is dezelfde praktijk onder twee verschillende namen. Sommige teams en leveranciers geven de voorkeur aan “endurance”, anderen aan “soak”; het meningsverschil is regionaal en stilistisch, niet technisch. Beide termen duiden op een langdurige, duurzame belasting om opstapeling te monitoren.
Waarom slaagde mijn soak-test, maar had de productie toch een geheugenlek?
Bijna altijd door een van de volgende vier redenen: de run was korter dan de verdubbelingstijd van het lek, de belasting was vlak terwijl productie een dagelijks patroon heeft, de run voerde nooit de geplande taak uit die lekt, of de testomgeving startte een proces opnieuw op dat de orchestrator in productie in leven zou hebben gehouden. Los het ontwerp op, niet de duur.
Ontdek hoe QAwerk 8 content-intensieve portalen stabiel hield onder duurzame verkeersstromen van 110 miljoen studenten per jaar, nog voordat Keystone verder opschaalde.