Storm antipattern újrapróbálkozás

Ha egy szolgáltatás nem érhető el vagy foglalt, ha az ügyfelek túl gyakran próbálkoznak újra a kapcsolatukkal, a szolgáltatás nehezen helyreállhat, és súlyosbíthatja a problémát. Nincs értelme az újrapróbálkozásnak is, mivel a kérések általában csak meghatározott ideig érvényesek.

A probléma leírása

A felhőben a szolgáltatások időnként problémákat tapasztalnak, és elérhetetlenné válnak az ügyfelek számára, vagy szabályozniuk vagy korlátozniuk kell az ügyfeleiket. Bár az ügyfeleknek ajánlott újrapróbálkozniuk a szolgáltatásokkal létesített sikertelen kapcsolatokon, fontos, hogy ne próbálkozzanak túl gyakran vagy túl sokáig. Az újrapróbálkozási próbálkozások rövid időn belül nem lesznek sikeresek, mivel a szolgáltatások valószínűleg nem fognak helyreállni. Emellett a szolgáltatások még nagyobb stressznek lehetnek kitéve, ha sok csatlakozási kísérlet történik a helyreállítás közben, és az ismétlődő csatlakozási kísérletek akár túlterhelhetik a szolgáltatást, és súlyosbíthatják a mögöttes problémát.

Az alábbi példa egy olyan forgatókönyvet mutat be, amelyben egy ügyfél egy kiszolgálóalapú API-hoz csatlakozik. Ha a kérés nem sikerül, az ügyfél azonnal újra próbálkozik, és örökre újra próbálkozik. Az ilyen viselkedés gyakran finomabb, mint ebben a példában, de ugyanez az elv érvényes.

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.
}

A probléma megoldása

Az ügyfélalkalmazások az ajánlott eljárásokat követve kerülik el az újrapróbálkozási vihart.

  • Korlátozza az újrapróbálkozási kísérletek számát, és ne próbálkozzon tovább hosszú ideig. Bár könnyen lehet hurkot while(true) írni, szinte biztosan nem szeretne hosszú ideig újra próbálkozni, mivel a kérés indításához vezető helyzet valószínűleg megváltozott. A legtöbb alkalmazásban elegendő néhány másodpercig vagy percig újrapróbálkozás.
  • Szünet az újrapróbálkozási kísérletek között. Ha egy szolgáltatás nem érhető el, nem valószínű, hogy az azonnali újrapróbálkozás sikeres lesz. Fokozatosan növelheti a kísérletek közötti várakozási időt, például exponenciális visszalépési stratégia használatával.
  • A hibák kezelése kecsesen történik. Ha a szolgáltatás nem válaszol, fontolja meg, hogy van-e értelme megszakítani a kísérletet, és visszaadni egy hibát az összetevő felhasználójának vagy hívójának. Az alkalmazás tervezésekor vegye figyelembe ezeket a hibaforgatókönyveket.
  • Fontolja meg a megszakító minta használatát, amely kifejezetten az újrapróbálkozási viharok elkerülése érdekében lett kialakítva.
  • Ha a kiszolgáló válaszfejlécet retry-after ad meg, győződjön meg arról, hogy a megadott időtartam leteltéig nem kísérli meg az újrapróbálkozást.
  • Az Azure-szolgáltatásokkal való kommunikációhoz használjon hivatalos SDK-kat. Ezek az SDK-k általában beépített újrapróbálkozási szabályzatokkal és védelemmel rendelkeznek az újrapróbálkozási viharok okozása vagy az ahhoz való hozzájárulás ellen. Ha olyan szolgáltatással kommunikál, amely nem rendelkezik SDK-val, vagy ha az SDK nem kezeli megfelelően az újrapróbálkozás logikáját, fontolja meg egy olyan kódtár használatát, mint a Polly (.NET esetén), vagy próbálkozzon újra (JavaScript esetén) az újrapróbálkozás logikájának helyes kezeléséhez, és kerülje a kód írását.
  • Ha olyan környezetben fut, amely támogatja azt, használjon szolgáltatáshálót (vagy egy másik absztrakciós réteget) a kimenő hívások küldéséhez. Ezek az eszközök, például a Dapr általában támogatják az újrapróbálkozási szabályzatokat, és automatikusan követik az ajánlott eljárásokat, például az ismétlődő kísérletek utáni visszalépést. Ez a megközelítés azt jelenti, hogy nem kell újrapróbálkozési kódot írnia.
  • Fontolja meg a kérelmek kötegelését és a kérelmek készletezésének használatát, ahol elérhető. Számos SDK kezeli a kérések kötegelését és a kapcsolatkészletezést az Ön nevében, ami csökkenti az alkalmazás által végrehajtott kimenő kapcsolati kísérletek teljes számát, bár továbbra is ügyelnie kell arra, hogy ne próbálkozzon túl gyakran ezekkel a kapcsolatokkal.

A szolgáltatásoknak meg kell védeniük magukat az újrapróbálkozásoktól.

  • Adjon hozzá egy átjáróréteget, hogy kikapcsolhassa a kapcsolatokat egy incidens során. Ez egy példa a Válaszfal mintára. Az Azure számos különböző átjárószolgáltatást biztosít különböző típusú megoldásokhoz, például a Front Doorhoz, Application Gateway és API Management.
  • A kérések szabályozása az átjárón, amely biztosítja, hogy ne fogadjon el annyi kérést, hogy a háttérösszetevők ne tudjanak tovább működni.
  • Ha szabályoz, küldjön vissza egy retry-after fejlécet, amely segít az ügyfeleknek megérteni, hogy mikor kell újra létrehozni a kapcsolatokat.

Megfontolandó szempontok

  • Az ügyfeleknek figyelembe kell venniük a visszaadott hiba típusát. Egyes hibatípusok nem a szolgáltatás hibáját jelzik, hanem azt jelzik, hogy az ügyfél érvénytelen kérést küldött. Ha például egy ügyfélalkalmazás hibaüzenetet 400 Bad Request kap, valószínűleg nem fog segíteni, ha újrapróbálja ugyanazt a kérést, mivel a kiszolgáló azt mondja, hogy a kérés érvénytelen.
  • Az ügyfeleknek figyelembe kell venniük a kapcsolatok újraaktiválásának idejét. Az újrapróbálkozáshoz szükséges idő hosszát az üzleti követelmények határozzák meg, és hogy ésszerű módon propagálja-e a hibát egy felhasználónak vagy hívónak. A legtöbb alkalmazásban elegendő néhány másodpercig vagy percig újrapróbálkozás.

A probléma észlelése

Az ügyfél szempontjából a probléma tünetei közé tartozhat a nagyon hosszú válaszidő vagy a feldolgozási idő, valamint a telemetriai adatok, amelyek a kapcsolat újrapróbálkozására tett ismétlődő kísérleteket jelzik.

A szolgáltatás szempontjából a probléma tünetei közé tartozhat az egyik ügyféltől érkező kérések nagy száma rövid időn belül, vagy egy ügyféltől érkező kérések nagy száma a kimaradásokból való helyreállítás során. A tünetek közé tartozhat a szolgáltatás helyreállítása során fellépő nehézség, vagy a szolgáltatás folyamatos kaszkádolt meghibásodása közvetlenül a hiba kijavítása után.

Diagnosztikai példa

Az alábbi szakaszok egy lehetséges újrapróbálkozási vihar észlelésének egyik megközelítését szemléltetik, mind az ügyféloldalon, mind a szolgáltatásoldalon.

Azonosítás ügyféltelemetria alapján

Azure-alkalmazás Insights rögzíti az alkalmazások telemetriáját, és elérhetővé teszi az adatokat a lekérdezéshez és a vizualizációhoz. A kimenő kapcsolatok függőségekként vannak nyomon követve, és a velük kapcsolatos információk elérhetők és diagramozhatók annak azonosításához, hogy egy ügyfél nagy számú kimenő kérést küld-e ugyanarra a szolgáltatásra.

Az alábbi gráf az Application Insights portál Metrikák lapjáról származik, és a Függőségi hibák metrika távoli függőség neve alapján felosztva jelenik meg. Ez azt a forgatókönyvet szemlélteti, amikor rövid időn belül nagy számú (több mint 21 000) sikertelen kapcsolati kísérlet történt egy függőségre.

Képernyőkép az Application Insightsról, amely egyetlen függőség 21 ezer függőségi hibáját mutatja 30 percen belül

Azonosítás kiszolgálói telemetria alapján

Előfordulhat, hogy a kiszolgálóalkalmazások nagy számú kapcsolatot észlelnek egyetlen ügyfélről. Az alábbi példában az Azure Front Door egy alkalmazás átjárójaként működik, és úgy lett konfigurálva, hogy minden kérést naplózzanak egy Log Analytics-munkaterületen.

Az alábbi Kusto-lekérdezés a Log Analyticsen futtatható. Azonosítja azokat az ügyfél IP-címeket, amelyek nagy számú kérést küldtek az alkalmazásnak az elmúlt napon.

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

A lekérdezés újrapróbálkozási vihar során történő végrehajtása nagyszámú csatlakozási kísérletet jelenít meg egyetlen IP-címről.

A Log Analytics képernyőképe, amelyen 81 608 bejövő kapcsolat látható egyetlen IP-címről a Front Door felé egy órán belül