Retry měl požadavek zachránit. Místo toho znásobil výpadek
Opakování požadavku umí překlenout krátkou síťovou chybu. Pokud jej však bez společného rozpočtu provádí několik vrstev služby, může z malého počtu chyb vytvořit provoz, který přetížené závislosti nedovolí zotavit se.
Výzkum a provozní dokumentace distribuovaných systémů se shodují v jednom bodě: retry není bezplatná pojistka. Google SRE uvádí názorný příklad, ve kterém čtyři pokusy na třech vrstvách mohou pro jedinou původní operaci vytvořit až 64 volání databáze. Dokumentace AWS popisuje stejný mechanismus jako zesílení práce v okamžiku, kdy je závislost nejméně schopná ji přijmout.
Číslo 64 není univerzální měření každého systému. Je to matematický důsledek konkrétní hloubky a počtu pokusů. Překvapivý detail spočívá v tom, že každá vrstva může mít lokálně rozumnou politiku, ale celek se chová destruktivně. Klient, API brána a aplikační služba nevědí, že všechny současně zachraňují stejný požadavek.
Manažerské shrnutí
01Retry spotřebovává kapacitu. Nový pokus přidává práci, spojení a čekání právě ve chvíli, kdy závislost často už kapacitu nemá.
02Rozpočet musí být pro celý řetězec. Tři lokální limity retry nevytvářejí jeden bezpečný limit. Mohou se násobit.
03Bez idempotence může vzniknout dvojí účinek. Opakované vytvoření, platba nebo změna stavu nesmí být považována za bezpečnou pouze proto, že první odpověď nedorazila.
Timeout neříká, zda se operace nestala
Klientský timeout znamená, že klient nedostal odpověď včas. Neznamená, že server požadavek neprovedl. U čtení může opakování pouze zvýšit zátěž. U zápisu může vytvořit dva zdroje, dvě rezervace nebo dvě finanční operace.
Bezpečný návrh proto potřebuje rozlišovat druh chyby a vlastnost operace. Trvalá validační chyba se neopakuje. Dočasná chyba může být vhodná pro retry, pokud je operace idempotentní nebo používá jednoznačný klíč požadavku. Přetížení vyžaduje čekání a omezení počtu pokusů. Neznámý výsledek zápisu často vyžaduje nejprve dotaz na stav, nikoli slepé zopakování.
Situace
Riziko slepého retry
Bezpečnější reakce
Chybný vstup
Stejný požadavek bude stále neplatný
Vrátit chybu bez retry a opravit vstup
Omezení kapacity
Další pokusy prodlužují přetížení
Backoff s jitterem, limit a respektování signálu serveru
Timeout po zápisu
Operace mohla proběhnout bez doručené odpovědi
Idempotency key nebo dotaz na stav operace
Krátká síťová chyba u čtení
Malé zvýšení zátěže
Omezený retry v jedné určené vrstvě
ARCHITEKTONICKÉ PRAVIDLO
Každá cesta požadavku musí mít jedno místo, které vlastní retry, jeden celkový časový rozpočet a jeden maximální počet pokusů. Ostatní vrstvy chybu předají, nikoli znovu násobí.
Backoff bez jitteru může klienty synchronizovat
Exponenciální prodlužování čekání snižuje frekvenci pokusů, ale samo o sobě nemusí stačit. Když tisíce klientů obdrží chybu ve stejnou chvíli a všechny čekají přesně stejný interval, znovu udeří společně. Jitter přidává náhodné rozložení v rámci čekacího okna a omezuje tak stádový efekt.
Ani jitter není úplná ochrana. Může ztížit reprodukci chování a neřeší situaci, kdy je celkový počet pokusů příliš vysoký. Proto se používá spolu s konečným deadlinem, tokenovým rozpočtem retry, řízeným odhazováním zátěže a omezením souběhu. Smyslem není maximalizovat pravděpodobnost úspěchu každého jednotlivého požadavku. Smyslem je zachovat schopnost systému dokončovat užitečnou práci.
METRIKA PRO PROVOZ
Měřte poměr všech pokusů k původním požadavkům, počet retry podle důvodu a podíl výsledků, které uspěly až po opakování. Bez této trojice nelze poznat, zda retry zvyšuje dostupnost, nebo pouze maskuje závislost a vytváří špičky.
Modelový scénář z praxe: automatická pomoc zablokovala návrat
Následující scénář je složený z typických incidentů. Databáze začala odmítat malou část požadavků kvůli krátkému přetížení. Klientská knihovna provedla dva další pokusy. API brána měla vlastní retry při timeoutu a aplikační služba znovu spouštěla celý workflow. Provoz databáze tak rostl rychleji než počet skutečných uživatelů.
Tým nejprve zvýšil kapacitu, ale po návratu běžného provozu zůstávala služba nestabilní. Akumulované retry dál držely databázi nad bezpečnou hranicí. Stabilizace přišla až po dočasném vypnutí opakování v horních vrstvách a po řízeném odhození části provozu. Následná změna ponechala retry pouze u nejbližšího klienta závislosti, zavedla společný deadline a rozpočet pokusů.
POZNÁMKA Z PRAXE
Pokud chybovost klesne až po výrazném omezení provozu, nestačí pouze restartovat servery. Je nutné zkontrolovat, zda staré fronty a retry stále nevytvářejí práci rychleji, než ji závislost dokáže dokončit.
Co z doporučení neplyne
Nulový retry by byl stejně hrubý závěr jako retry všude. Krátké přechodné chyby jsou běžnou vlastností distribuovaných systémů a omezené opakování může dostupnost významně zlepšit. Rozhoduje bezpečnost operace, místo v řetězci, dostupná kapacita a schopnost klienta respektovat celkový deadline.
Také nelze převzít jeden počet pokusů pro všechny služby. Levné idempotentní čtení snese jiný režim než pomalý zápis do sdílené databáze. Výzkum a doporučení dodavatelů poskytují principy, ale konkrétní hranice musí určit zatěžovací a poruchový test daného systému.
HRANICE DŮKAZU
Exponenciální backoff s jitterem snižuje synchronizaci klientů. Neprokazuje, že závislost má dost kapacity, že operace je idempotentní ani že několik vrstev nesdílí skrytý násobící mechanismus.
Retry musí mít vlastníka stejně jako kapacita
Politika retry bývá rozptýlená v SDK, service mesh, API bráně a aplikačním kódu. V důsledku toho ji nikdo nevnímá jako jednu provozní kontrolu. Pro kritické cesty je vhodné evidovat vlastníka, celkový deadline, povolené chyby, idempotenci, limit pokusů a chování při vyčerpání rozpočtu.
Nosná teze zní: retry je spotřebitel kapacity, nikoli jen obsluha chyby. Organizace jej musí navrhovat a testovat se stejnou disciplínou jako fronty, limity a odhazování provozu.