Dela via


Mönster för konkurrerande konsumenter

Gör så att flera samtidiga användare kan bearbeta meddelanden som tas emot på samma meddelandekanal. Med flera samtidiga konsumenter kan ett system bearbeta flera meddelanden samtidigt för att optimera dataflödet, förbättra skalbarheten och tillgängligheten och balansera arbetsbelastningen.

Kontext och problem

Ett molnprogram hanterar ofta ett stort antal begäranden. I stället för att bearbeta varje begäran synkront kan programmet skicka begäranden via ett meddelandesystem till en konsumenttjänst som hanterar dem asynkront. Den här strategin hjälper till att förhindra att bearbetning av begäranden blockerar programmets affärslogik.

Antalet begäranden kan variera avsevärt över tid. En plötslig ökning av användaraktivitet eller aggregerade begäranden från flera klienter kan skapa en oförutsägbar arbetsbelastning. Vid hög belastning kan ett system behöva bearbeta många hundratals begäranden per sekund. Vid andra tillfällen kan antalet vara litet. Dessutom kan det arbete som krävs för att hantera dessa begäranden variera kraftigt. Om du använder en enda konsumenttjänstinstans kan begäranden överbelasta den instansen. Eller en tillströmning av programmeddelanden kan överbelasta meddelandesystemet.

För att hantera den här fluktuerande arbetsbelastningen kan systemet köra flera konsumenttjänstinstanser. Systemet måste dock samordna dessa konsumenter för att säkerställa att varje meddelande endast levereras till en konsument. Systemet måste också balansera arbetsbelastningen mellan konsumenter för att förhindra att en instans blir en flaskhals.

Lösning

Använd en meddelandekö för att implementera kommunikationskanalen mellan programmet och konsumenttjänstinstanserna. Programmet skickar begäranden som meddelanden till kön och konsumenttjänstinstanser tar emot och bearbetar meddelanden från kön. Med den här metoden kan samma pool med konsumenttjänstinstanser hantera meddelanden från alla instanser av programmet. Följande diagram visar hur en meddelandekö distribuerar arbete till tjänstinstanser.

Diagram som visar hur en meddelandekö distribuerar arbete till tjänstinstanser.

Anmärkning

Flera konsumenter får dessa meddelanden, men mönstret Konkurrerande konsumenter skiljer sig från mönstretPublisher-Subscriber. I mönstret Konkurrerande konsumenter får en konsument varje meddelande för bearbetning. I Publisher-Subscriber-mönstret får alla konsumenter varje meddelande.

Den här lösningen har följande fördelar:

  • Det tillhandahåller ett belastningsutjämnat system som kan hantera stora variationer i begärandevolymer från programinstanser. Kön fungerar som en buffert mellan programinstanser och konsumenttjänstinstanser. Den här bufferten kan minimera effekten på tillgängligheten och svarstiden för både program- och tjänstinstanserna. Mer information finns i Mönster för köbaserad belastningsutjämning. Ett meddelande som kräver viss långvarig bearbetning hindrar inte andra konsumenttjänstinstanser från att bearbeta andra meddelanden samtidigt.

  • Det förbättrar tillförlitligheten. Om en producent kommunicerar direkt med en konsument i stället för att använda det här mönstret och inte övervakar konsumenten, står den inför en hög sannolikhet att förlora meddelanden eller misslyckas med att bearbeta dem när konsumenten misslyckas. I det här mönstret skickar systemet inte meddelanden till en specifik tjänstinstans. En misslyckad tjänstinstans blockerar inte en producent och alla arbetstjänstinstanser kan bearbeta meddelanden.

  • Det kräver inte komplex samordning mellan konsumenter eller mellan producent- och konsumentinstanser. Meddelandekön säkerställer att varje meddelande levereras minst en gång.

  • Den skalar. När du använder autoskalning kan systemet dynamiskt öka eller minska antalet konsumenttjänstinstanser när meddelandevolymen varierar.

  • Det kan förbättra återhämtningen om meddelandekön tillhandahåller transaktionella läsåtgärder. Om en konsumenttjänstinstans läser och bearbetar ett meddelande som en del av en transaktionsåtgärd och misslyckas kan det här mönstret säkerställa att meddelandet returneras till kön så att en annan konsumenttjänstinstans kan bearbeta det. För att minska risken för kontinuerliga meddelandefel rekommenderar vi att du använder köer med obeställbara meddelanden.

Problem och överväganden

Tänk på följande när du bestämmer hur du ska implementera det här mönstret:

  • Meddelandeordning: Ordningen i vilken konsumenttjänstinstanser tar emot meddelanden är inte garanterad och visar inte nödvändigtvis i vilken ordning meddelandena skapades. Utforma systemet så att det bearbetar meddelanden idempotent. Den här designen hjälper till att eliminera bearbetningsordningsberoenden.

    Azure Service Bus kan implementera garanterad första-i-först-ut-ordning av meddelanden och andra mönster med hjälp av meddelandesessioner.

  • Krav på tjänståterhämtning: Om systemet identifierar och startar om tjänstinstanser som har misslyckats kan det behöva göra de åtgärder som dessa tjänstinstanser utför idempotenta för att minimera effekterna vid bearbetning av ett enda meddelande mer än en gång.

  • Identifiering av giftmeddelanden: Ett felformat meddelande eller en uppgift som kräver åtkomst till resurser som inte är tillgängliga kan orsaka att en tjänstinstans fallerar. Systemet bör förhindra att dessa meddelanden återgår till kön på obestämd tid och i stället samla in och lagra informationen någon annanstans för analys om det behövs. Service Bus kan automatiskt skicka meddelanden till en dead-letter-kö när leveransantalet överskrider det konfigurerade tröskelvärdet MaxDeliveryCount.

  • Resultathantering: Tjänstinstansen som hanterar ett meddelande är helt frikopplad från programlogik som genererar meddelandet, så de kanske inte kan kommunicera direkt. Om tjänstinstansen genererar resultat som måste gå tillbaka till programlogik lagrar du den här informationen på en plats som båda komponenterna kan komma åt. För att förhindra att programlogik hämtar ofullständiga data måste systemet ange när bearbetningen är klar. En arbetsprocess kan skicka resultat tillbaka till programlogik via en dedikerad meddelandesvarskö. Programlogiken måste kunna korrelera dessa resultat med det ursprungliga meddelandet.

  • Skalning av meddelandesystem: I en storskalig lösning kan hög meddelandevolym överbelasta en enda meddelandekö och förvandla den till en systemflaskhals. I den här situationen bör du överväga att partitionera meddelandesystemet för att skicka meddelanden från specifika producenter till en specifik kö eller belastningsutjäxla för att distribuera meddelanden över flera meddelandeköer.

  • Tillförlitlighet för meddelandesystem: Använd ett tillförlitligt meddelandesystem för att garantera att meddelanden inte går förlorade när programmet har lagt till dem. Den här funktionen är viktig för att säkerställa att alla meddelanden levereras minst en gång.

När du ska använda det här mönstret

Använd det här mönstret i sådana här scenarier:

  • Programarbetsbelastningen är indelad i uppgifter som kan köras asynkront.

  • Uppgifterna är fristående och kan köras parallellt.

  • Arbetsvolymen är mycket varierande och kräver en skalbar lösning.

  • Lösningen måste ge hög tillgänglighet och förbli motståndskraftig när uppgiftsbearbetningen misslyckas.

Det här mönstret kanske inte är lämpligt när:

  • Du kan inte enkelt dela upp programarbetsbelastningen i diskreta uppgifter, eller så finns det en hög grad av beroende mellan aktiviteter.

  • Aktiviteter måste köras synkront och programlogik måste vänta tills varje aktivitet har slutförts innan den fortsätter.

  • Aktiviteter måste köras i en viss sekvens.

Anmärkning

Vissa meddelandesystem stöder sessioner som låter en producent gruppera meddelanden tillsammans och se till att samma konsument hanterar alla meddelanden i gruppen. Du kan använda den här mekanismen med prioriterade meddelanden när det stöds för att framtvinga meddelandeordning och leverera meddelanden i följd från en producent till en enskild konsument.

Design av arbetsbelastning

Utvärdera hur du använder mönstret Konkurrerande konsumenter i en arbetsbelastnings design för att hantera de mål och principer som beskrivs i Grundpelarna i Azure Well-Architected Framework. Följande tabell innehåller vägledning om hur det här mönstret stöder målen för varje pelare.

Grundpelare Så här stöder det här mönstret pelarmål
Tillförlitlighets designbeslut hjälper din arbetsbelastning att bli motståndskraftig mot funktionsfel och säkerställer att den återställer sig till ett fullständigt fungerande tillstånd när ett fel uppstår. Det här mönstret skapar redundans i köbearbetning genom att behandla konsumenter som repliker, så ett instansfel hindrar inte andra konsumenter från att bearbeta kömeddelanden.

- RE:05 Redundans
- Bakgrundsjobb
Kostnadsoptimering fokuserar på att upprätthålla och förbättra arbetsbelastningens avkastning på investeringen. Det här mönstret kan hjälpa till att optimera kostnaderna eftersom det skalas baserat på ködjup och kan skalas ned till noll när kön är tom. Det kan också optimera kostnaderna eftersom du kan begränsa det maximala antalet samtidiga konsumentinstanser.

- CO:05 Hastighetsoptimering
- CO:07 Komponentkostnader
Prestandaeffektivitet hjälper din arbetsbelastning effektivt uppfylla kraven genom optimering av skalning, data och kod. Det här mönstret distribuerar belastningen mellan konsumentnoder för att öka användningen och dynamisk skalning baserat på ködjup minimerar överetablering.

- PE:05 Skalning och partitionering
- PE:07 Kod och infrastruktur

Om detta mönster inför kompromisser inom en pelare bör du överväga dem mot målen för de andra pelarna.

Exempel

Azure tillhandahåller Service Bus-köer och Azure Functions-köutlösare som tillsammans implementerar det här molndesignmönstret direkt. Functions integreras med Service Bus via utlösare och bindningar. Med den här integreringen kan du skapa funktioner som använder kömeddelanden från utgivare. När applikationer publiceras skickas meddelanden till en kö, och konsumenter som implementeras som funktioner kan hämta och hantera dessa meddelanden.

För återhämtning låter en Service Bus-kö en konsument använda PeekLock-läge när det hämtar ett meddelande från kön. Det här läget behåller meddelandet men döljer det från andra konsumenter. Funktionen tar emot ett meddelande i PeekLock-läge. Om funktionen slutförs framgångsrikt, anropar körningen Complete på meddelandet. Om funktionen misslyckas kan körtiden anropa Abandon och göra meddelandet synligt igen så att en annan konsument kan hämta det. Om funktionen körs längre än PeekLock-tidsgränsen förnyas låset automatiskt så länge funktionen körs.

Diagram som använder Service Bus för att distribuera arbete till Functions.

Functions skalar automatiskt antalet konsumentinstanser baserat på ködjup och trafik. Med den här skalningen kan lösningen hantera arbetstoppar samtidigt som kostnaderna minimeras under perioder med låg volym. Om Functions skapar flera instanser konkurrerar de genom att självständigt hämta och bearbeta meddelanden. Mer information finns i Service Bus-köer, teman och prenumerationer och Service Bus-utlösare för Funktioner.

Mer information om hur du använder Service Bus-klientbiblioteket för .NET för att skicka meddelanden till en Service Bus-kö finns i de publicerade exemplen.

Nästa steg

  • Välj en meddelandetjänst i Azure: Lär dig hur olika Azure-meddelandetjänster som Service Bus, Azure Storage-köer, Azure Event Hubs och Azure Event Grid stöder asynkrona kommunikationsmönster och hur du väljer rätt tjänst- och meddelandemodell för ditt scenario.

  • Metodtips för automatisk skalning: Lär dig hur du utformar lösningar som skalar ut konsumentinstanser baserat på arbetsbelastning, t.ex. kölängd eller meddelandedataflöde, så att du kan hantera belastningstoppar och kontrollkostnader under perioder med låg aktivitet.

  • Mönster för konsolidering av beräkningsresurser: Du kanske kan konsolidera flera instanser av en konsumenttjänst i en enda process för att minska kostnaderna och hanteringskostnaderna. Mönstret Konsolidering av beräkningsresurser beskriver fördelarna och kompromisserna med den här metoden.

  • Mönster för köbaserad belastningsutjämning: En meddelandekö kan ge systemet återhämtning. Återhämtning gör att tjänstinstanser kan hantera mycket varierande volymer av begäranden från programinstanser. Meddelandekön fungerar som en buffert som jämnar ut belastningen. Mönstret för köbaserad belastningsutjämning beskriver det här scenariot i detalj.