Antipattern opakování Stormu

Pokud je služba nedostupná nebo zaneprázdněná, může příliš časté opakování připojení klienty způsobit, že služba bude mít potíže s obnovením a může problém ještě zhoršit. Také nemá smysl opakovat pokusy napořád, protože požadavky jsou obvykle platné pouze po definovanou dobu.

Popis problému

V cloudu mají služby občas problémy a stávají se nedostupnými pro klienty nebo musí omezit nebo omezit rychlost svých klientů. I když je vhodné, aby klienti opakovat neúspěšná připojení ke službám, je důležité, aby to nezkoušel příliš často nebo příliš dlouho. Opakování během krátké doby pravděpodobně nebudou úspěšná, protože služby se pravděpodobně nenapraví. Služby mohou být navíc ještě více zatížené, pokud se během pokusu o obnovení provádí velké množství pokusů o připojení, a opakované pokusy o připojení mohou službu dokonce zahltit a zhoršit základní problém.

Následující příklad ukazuje scénář, kdy se klient připojuje k rozhraní API založenému na serveru. Pokud požadavek nebude úspěšný, klient se okamžitě zopakuje a bude se neustále opakovat. Tento druh chování je často jemnější než v tomto příkladu, ale platí stejný princip.

public async Task<string> GetDataFromServer()
{
    while(true)
    {
        var result = await httpClient.GetAsync(string.Format("http://{0}:8080/api/...", hostName));
        if (result.IsSuccessStatusCode) break;
    }

    // ... Process result.
}

Jak problém vyřešit

Klientské aplikace by se měly řídit některými osvědčenými postupy, aby se zabránilo vzniku zamíchaní opakování.

  • Zakažte počet pokusů o opakování a nepokoušejete se to opakovat po dlouhou dobu. I když se může zdát, že psaní smyčky je snadné, téměř určitě nechcete opakovat pokus po dlouhou dobu, protože situace, která vedla ke spuštění požadavku, se while(true) pravděpodobně změnila. Ve většině aplikací stačí několik sekund nebo minut opakování.
  • Pozastavit mezi pokusy o opakování. Pokud je služba nedostupná, je nepravděpodobné, že by okamžité opakování bylo úspěšné. Postupně zvětšete dobu čekání mezi pokusy, například pomocí exponenciální strategie opakování.
  • Řádně zacházet s chybami. Pokud služba nereaguje, zvažte, jestli má smysl pokus přerušit a vrátit chybu zpět uživateli nebo volajícímu vaší komponenty. Při navrhování aplikace zvažte tyto scénáře selhání.
  • Zvažte použití modelu Jistič,který je navržený speciálně tak, aby se zabránilo opakování zamíchání.
  • Pokud server poskytuje retry-after hlavičku odpovědi, ujistěte se, že se nepokoušejte o opakování, dokud ne uplyne zadané časové období.
  • Při komunikaci se službami Azure používejte oficiální verze SDK. Tyto sdk obecně mají předdefinované zásady opakování a ochranu před tím, než způsobí opakování zachytátek nebo se k nim přispívá. Pokud komunikujete se službou, která nemá sadu SDK, nebo pokud sada SDK nezvládá logiku opakování správně, zvažte použití knihovny jako Polly (pro .NET) nebo opakování (pro JavaScript), abyste správně zvládli logiku opakování a vyhnuli se psaní kódu sami.
  • Pokud používáte prostředí, které to podporuje, použijte k odesílání odchozích volání síť služeb (nebo jinou abstraktní vrstvu). Tyto nástroje, jako je Dapr,obvykle podporují zásady opakování a automaticky dodržují osvědčené postupy, jako je například vypnutí po opakovaných pokusech. Tento přístup znamená, že nemusíte psát kód opakování sami.
  • Zvažte dávkování požadavků a použití sdružování požadavků tam, kde je to možné. Mnoho sdk za vás zovládá dávkování požadavků a sdružování připojení, což sníží celkový počet pokusů o odchozí připojení, které vaše aplikace provede, i když stále musíte být opatrní, abyste tato připojení příliš často nezkoušel opakovat.

Služby by se také měly chránit před opakováním zatáčky.

  • Přidejte vrstvu brány, abyste mohli během incidentu vypnout připojení. Toto je příklad vzoru Bulkhead. Azure poskytuje mnoho různých služeb brány pro různé typy řešení, včetně Front Door, Application Gatewaya API Management.
  • Omezení požadavků na bránu, což zajišťuje, že nebudete přijímat tolik požadavků, aby back-endové komponenty nepomáhaly v provozu.
  • Pokud omezování používáte, odešlete zpátky hlavičku, která klientům pomůže pochopit, kdy se mají retry-after jejich připojení znovu vracet.

Požadavky

  • Klienti by měli zvážit typ vrácené chyby. Některé typy chyb neznačí selhání služby, ale značí, že klient odeslal neplatný požadavek. Pokud například klientská aplikace obdrží chybovou odpověď, opakování stejného požadavku pravděpodobně nepomůže, protože server vám říká, že váš požadavek 400 Bad Request není platný.
  • Klienti by měli vzít v úvahu dobu, po kterou má smysl připojení znovu attemptovat. Doba, po kterou byste měli opakování opakovat, bude řízena vašimi obchodními požadavky a zda můžete přiměřeně rozšířit chybu zpět na uživatele nebo volajícího. Ve většině aplikací stačí několik sekund nebo minut opakování.

Jak zjistit problém

Z pohledu klienta mohou příznaky tohoto problému zahrnovat velmi dlouhou dobu odezvy nebo zpracování a také telemetrii, která indikuje opakované pokusy o opakování připojení.

Z pohledu služby by příznaky tohoto problému mohly během krátké doby zahrnovat velký počet požadavků od jednoho klienta nebo velký počet požadavků od jednoho klienta při zotavení z výpadků. Příznaky mohou zahrnovat také potíže s obnovením služby nebo probíhající kaskádová selhání služby hned po opravě chyby.

Ukázková diagnostika

Následující části ilustrují jeden přístup ke zjištění potenciálního opakování stormu na straně klienta i na straně služby.

Identifikace z telemetrie klienta

Azure Application Přehledy zaznamenává telemetrii z aplikací a zviditele dat pro dotazování a vizualizaci. Odchozí připojení se sledují jako závislosti a k informacím o nich je možné přistupovat a zmapovat je, aby bylo možné identifikovat, kdy klient provádí ve stejné službě velký počet odchozích požadavků.

Následující graf byl převzat z karty Metriky na portálu Application Přehledy a zobrazuje metriku Selhání závislostí rozdělenou podle názvu vzdálené závislosti. To znázorňuje scénář, kdy během krátké doby došlo k velkému počtu (více než 21 000) neúspěšných pokusů o připojení k závislosti.

Snímek obrazovky Přehledy s 21 000 selháními závislosti na jedné závislosti během 30 minut

Identifikace z telemetrie serveru

Serverové aplikace mohou být schopny zjišťovat velký počet připojení z jednoho klienta. V následujícím příkladu Azure Front Door funguje jako brána pro aplikaci a je nakonfigurovaná tak, aby všechny požadavky protokoloval do pracovního prostoru služby Log Analytics.

Následující dotaz Kusto je možné spustit ve službě Log Analytics. Identifikuje IP adresy klientů, které do aplikace za poslední den odeslaly velký počet požadavků.

AzureDiagnostics
| where ResourceType == "FRONTDOORS" and Category == "FrontdoorAccessLog"
| where TimeGenerated > ago(1d)
| summarize count() by bin(TimeGenerated, 1h), clientIp_s
| order by count_ desc

Při spuštění tohoto dotazu během opakování stormu se zobrazí velký počet pokusů o připojení z jedné IP adresy.

Snímek obrazovky s Log Analytics zobrazující 81 608 příchozích připojení k Front Door z jedné IP adresy během hodinové doby