Antimönstret Försök storm igen
När en tjänst är otillgänglig eller upptagen kan klienter som försöker med sina anslutningar igen för ofta få tjänsten att få problem med återställningen och kan göra problemet värre. Det är inte heller meningsfullt att försöka igen för alltid, eftersom begäranden vanligtvis bara är giltiga under en angiven tidsperiod.
Problembeskrivning
I molnet upplever tjänster ibland problem och blir otillgängliga för klienter eller måste begränsa eller begränsa sina klienter. Även om det är en bra idé för klienter att försöka igen misslyckade anslutningar till tjänster, är det viktigt att de inte försöker igen för ofta eller för länge. Återförsök inom en kort tidsperiod kommer troligen inte att lyckas eftersom tjänsterna troligtvis inte har återställts. Dessutom kan tjänster bli ännu mer stressade när många anslutningsförsök görs medan de försöker återställas, och upprepade anslutningsförsök kan till och med överbelasta tjänsten och göra det underliggande problemet värre.
I följande exempel visas ett scenario där en klient ansluter till ett serverbaserat API. Om begäran inte lyckas försöker klienten igen omedelbart och fortsätter att försöka för alltid. Den här typen av beteende är ofta mer diskret än i det här exemplet, men samma princip gäller.
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.
}
Så åtgärdar du problemet
Klientprogram bör följa några metodtips för att undvika att orsaka en storm för återförsök.
- Minska antalet återförsök och försök inte igen under en längre tid. Även om det kan verka enkelt att skriva en loop vill du förmodligen inte göra ett nytt försök under en längre tid, eftersom den situation som ledde till att begäran initierades förmodligen har
while(true)ändrats. I de flesta program räcker det att försöka igen i några sekunder eller minuter. - Pausa mellan återförsök. Om en tjänst inte är tillgänglig kommer det sannolikt inte att lyckas att försöka igen omedelbart. Öka gradvis den tid du väntar mellan försök, till exempel genom att använda en exponentiell backoff-strategi.
- Hantera fel på ett smidigt sätt. Om tjänsten inte svarar bör du fundera på om det är klokt att avbryta försöket och returnera ett fel tillbaka till användaren eller anroparen av komponenten. Tänk på dessa felscenarier när du utformar ditt program.
- Överväg att använda kretsbrytarmönstret, som är särskilt utformat för att undvika stormar på nytt.
- Om servern tillhandahåller ett svarshuvud kontrollerar du att du inte försöker
retry-afterigen förrän den angivna tidsperioden har förflutit. - Använd officiella SDK:er när du kommunicerar med Azure-tjänster. Dessa SDK:er har vanligtvis inbyggda återförsöksprinciper och skydd mot att orsaka eller bidra till stormförsök. Om du kommunicerar med en tjänst som inte har något SDK, eller om SDK:n inte hanterar logik för omförsök på rätt sätt, bör du överväga att använda ett bibliotek som Polly (för .NET) eller försöka igen (för JavaScript) för att hantera logiken för omförsök på rätt sätt och undvika att skriva koden själv.
- Om du kör i en miljö som stöder det använder du ett tjänstnät (eller ett annat abstraktionslager) för att skicka utgående anrop. Dessa verktyg, till exempel Dapr,stöder vanligtvis återförsöksprinciper och följer automatiskt metodtips, som att backa av efter upprepade försök. Den här metoden innebär att du inte behöver skriva kod för återförsök själv.
- Överväg att batcha begäranden och använda poolning av begäranden där det är tillgängligt. Många SDK:er hanterar batchbearbetning av förfrågningar och anslutningspooler åt dig, vilket minskar det totala antalet utgående anslutningsförsök som ditt program gör, även om du fortfarande behöver vara noga med att inte försöka göra dessa anslutningar för ofta.
Tjänsterna bör också skydda sig mot återförsöksstormningar.
- Lägg till ett gatewaylager så att du kan stänga av anslutningar under en incident. Det här är ett exempel på mönstret Bulkhead. Azure tillhandahåller många olika gateway-tjänster för olika typer av lösningar, Front Door,Application Gatewayoch API Management.
- Begränsa begäranden vid din gateway, vilket säkerställer att du inte accepterar så många begäranden att dina backend-komponenter inte kan fortsätta att fungera.
- Om du är begränsning skickar du tillbaka ett -huvud för att hjälpa klienterna att förstå
retry-afternär de ska försöka försöka igen.
Överväganden
- Klienter bör överväga vilken typ av fel som returneras. Vissa feltyper indikerar inte ett fel i tjänsten, utan indikerar i stället att klienten har skickat en ogiltig begäran. Om ett klientprogram till exempel får ett felsvar hjälper det förmodligen inte att försöka igen med samma begäran eftersom servern talar om för dig att din
400 Bad Requestbegäran inte är giltig. - Klienter bör överväga hur lång tid det är meningsfullt att försöka försöka göra om anslutningar. Hur lång tid du bör försöka för styrs av dina affärskrav och om du rimligen kan sprida ett fel tillbaka till en användare eller anropare. I de flesta program räcker det att försöka igen i några sekunder eller minuter.
Så identifierar du problemet
Från en klients perspektiv kan symptom på det här problemet omfatta mycket långa svarstider eller bearbetningstider, tillsammans med telemetri som indikerar upprepade försök att försöka ansluta igen.
Ur en tjänsts perspektiv kan symptom på det här problemet omfatta ett stort antal begäranden från en klient inom en kort tidsperiod, eller ett stort antal begäranden från en enda klient under återställning från avbrott. Symtomen kan också vara problem med att återställa tjänsten eller pågående sammanhängande fel i tjänsten direkt efter att ett fel har reparerats.
Exempeldiagnos
I följande avsnitt visas en metod för att identifiera en potentiell storm för återförsök, både på klientsidan och på tjänstsidan.
Identifiera från klienttelemetri
Azure Application Insights registrerar telemetri från program och gör data tillgängliga för frågor och visualisering. Utgående anslutningar spåras som beroenden och information om dem kan nås och visas för att identifiera när en klient gör ett stort antal utgående begäranden till samma tjänst.
Följande diagram har tagits från fliken Mått i Application Insights-portalen och visar måttet Beroendefel uppdelat efter fjärrberoendenamn. Detta illustrerar ett scenario där det fanns ett stort antal (över 21 000) misslyckade anslutningsförsök till ett beroende inom kort.

Identifiera från servertelemetri
Serverprogram kan identifiera ett stort antal anslutningar från en enda klient. I följande exempel fungerar Azure Front Door en gateway för ett program och har konfigurerats för att logga alla begäranden till en Log Analytics-arbetsyta.
Följande Kusto-fråga kan köras mot Log Analytics. Den identifierar klient-IP-adresser som har skickat ett stort antal begäranden till programmet under den senaste dagen.
AzureDiagnostics
| where ResourceType == "FRONTDOORS" and Category == "FrontdoorAccessLog"
| where TimeGenerated > ago(1d)
| summarize count() by bin(TimeGenerated, 1h), clientIp_s
| order by count_ desc
När den här frågan körs under en storm för återförsök visas ett stort antal anslutningsförsök från en enda IP-adress.
