Megosztás a következőn keresztül:


Újrapróbálkozási storm antipattern

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 ronthatja a problémát. Nem érdemes örökké próbálkozni, 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. Habár az ügyfelek számára jó gyakorlat, hogy újra próbálkozzanak a sikertelen kapcsolódások esetén, fontos, hogy ne tegyék ezt túl gyakran vagy túl hosszú ideig. Az újrapróbálkozás rövid időn belül valószínűleg nem fog sikerülni, mivel a szolgáltatások valószínűleg nem fognak helyreállni. Emellett a szolgáltatások még nagyobb terhelésnek lehetnek kitéve, ha sok kapcsolati kísérlet történik a helyreállításuk során, és az ismétlődő csatlakozási kísérletek akár túlterhelhetik a szolgáltatást, és tovább ronthatjá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. Ez a fajta 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 kövessenek néhány ajánlott eljárást, hogy ne okozzanak újrapróbálkozási vihart.

  • Korlátozza az újrapróbálkozások számát, és ne próbálkozzon tovább hosszú ideig. Bár könnyűnek tűnhet egy while(true) ciklust írni, szinte biztosan nem szeretne hosszú ideig újra próbálkozni, mivel a kérelem 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, az azonnali újrapróbálkozás nem valószínű, hogy sikerül. 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 elegánsan. 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 circuit breaker minta használatát, amely kifejezetten az újrapróbálkozási viharok elkerülésére lett tervezve.
  • Ha a kiszolgáló egy retry-after válaszfejlécet biztosít, győződjön meg arról, hogy a megadott időtartam elteltéig nem kísérel meg újra próbálkozni.
  • Hivatalos SDK-k használata az Azure-szolgáltatásokkal való kommunikációhoz. 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 az olyan kódtárak használatát, mint Polly (.NET esetén) vagy újrapróbálkozással (JavaScript esetén), hogy megfelelően kezelje az újrapróbálkozás logikáját, és ne írja meg a kódot.
  • 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 a visszalépést ismétlődő próbálkozások után. Ez a megközelítés azt jelenti, hogy nem kell újrapróbálkozó kódot írnia.
  • Fontolja meg a kérelmek kötegelését és a kéréskészletezés 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 ügyelnie kell arra, hogy ne próbálkozzon túl gyakran.

A szolgáltatásoknak meg kell védeniük magukat a túl sok újrapróbálkozás okozta problémáktól.

  • Adjon hozzá egy átjáróréteget, hogy egy incidens során kikapcsolhassa a kapcsolatokat. Ez egy példa a Bulkhead pattern-ra. Az Azure számos különböző átjárószolgáltatást biztosít különböző megoldásokhoz, például Front Door, Application Gatewayés API Management.
  • Az átjárón keresztül szabályozza a kéréseket, így biztos lehet benne, hogy nem fogad el olyan sok kérést, hogy a backend komponensek ne tudjanak tovább működni.
  • Ha korlátozást alkalmaz, küldjön vissza egy retry-after fejlécet, amely segít az ügyfeleknek megérteni, hogy mikor kell megpróbálni újra csatlakozni.

Megfontolások

  • 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érelmet küldött. Ha például egy ügyfélalkalmazás 400 Bad Request hibaüzenetet kap, valószínűleg nem fog segíteni a kérés újraküldése, mivel a kiszolgáló azt jelzi, hogy a kérés nem érvényes.
  • Az ügyfeleknek figyelembe kell venniük azt az időtartamot, amely értelmes a kapcsolatok újrapróbálásához. Az újrapróbálkozáshoz szükséges időtartamot az üzleti követelmények határozzák meg, és hogy észszerűen terjeszthet-e 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álasz- vagy feldolgozási idő, valamint a kapcsolat újrapróbálkozására tett ismétlődő kísérleteket jelző telemetriai adatok.

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ásakor 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.

Példadiagnózis

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 Application Insights rögzíti az alkalmazások telemetriáját, és elérhetővé teszi az adatokat lekérdezéshez és vizualizációhoz. A kimenő kapcsolatok függőségekként vannak nyomon követve, és a róluk szóló információk elérhetők és diagramozhatók annak azonosítására, hogy egy ügyfél nagy számú kimenő kérést küld-e ugyanahhoz a szolgáltatáshoz.

Az alábbi grafikon az Application Insights portál Metrikák lapjáról készült, és megmutatja a -függőségi hibák metrikát, felosztva a távoli függőség neveszerint. 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.

Az Application Insights képernyőképe, amelyen egyetlen függőség 21 ezer függőségi hibája látható egy 30 perces időszakon belül

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

Előfordulhat, hogy a kiszolgálóalkalmazások nagy számú kapcsolatot képesek észlelni egyetlen ügyfélbő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 naplózza egy Log Analytics-munkaterületre irányuló összes kérést.

Az alábbi Kusto-lekérdezés a Log Analytics használatával hajtható végre. 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 Doorhoz egy órán belül