Kommentar
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Gruppera relaterade meddelanden efter en kategorinyckel och bearbeta varje grupp sekventiellt, ett meddelande i taget, samtidigt som olika grupper bearbetas parallellt.
Det här mönstret löser spänningen mellan att upprätthålla fifo-korrekthet (first-in, first-out) inom varje logisk grupp och skala ut samtidig bearbetning mellan grupper. Utformningen säkerställer att krav på ordningsföljd inte blir en systemomfattande flaskhals.
Kontext och problem
Program behöver ofta bearbeta relaterade meddelanden i den ordning de anländer samtidigt som de skalas ut för att hantera ökad belastning. I en distribuerad arkitektur är det här kravet svårt att uppnå eftersom arbetare självständigt hämtar meddelanden från en delad kö. När flera arbetare konkurrerar om meddelanden, som i mönstret Konkurrerande konsumenter, delas ordningen upp.
Överväg ett orderspårningssystem som tar emot en ström av åtgärder, till exempel att skapa en order, lägga till en transaktion, ändra en tidigare transaktion och ta bort en order. Varje beställnings åtgärder måste bearbetas i FIFO-ordning, eftersom om de tillämpas i fel ordning skadas ordningens tillstånd. Den inkommande kön mellanläser dock åtgärder över många beställningar. En enskild konsument som framtvingar global beställning blir en flaskhals och flera konsumenter kan bearbeta samma orderåtgärder i fel ordning.
De enkla metoderna för det här problemet delas upp på olika sätt:
Enskild konsument. En enskild konsument bevarar meddelandeordningen eftersom den bearbetar ett meddelande i taget, men den kan inte skalas för att hantera ökat dataflöde.
Flera konkurrerande konsumenter. Flera konsumenter skalar dataflödet genom att dra meddelanden parallellt, men de förlorar ordergarantier per grupp. Två arbetare kan hämta meddelanden i följd för samma ordning och bearbeta dem samtidigt eller ur sekvens, vilket skadar ordertillståndet.
Lösning
Mönstret Sekventiell konvoj partitionerar relaterade meddelanden i kategorier och bearbetar varje kategori sekventiellt, ett meddelande i taget, medan kategorier bearbetas parallellt.
Mönstret fungerar genom att tilldela varje meddelande en kategorinyckel som identifierar den grupp som den tillhör. En meddelandekö använder den här nyckeln för att partitionera meddelanden i logiska grupper. I varje grupp framtvingar mäklaren FIFO-beställning så att en konsument som låser en grupp tar emot meddelanden strikt i den sekvens som de har angetts. Olika grupper kan bearbetas av olika konsumenter samtidigt, så systemet skalas horisontellt mellan grupper utan att offra ordningen inom en enskild grupp.
På Azure ger Azure Service Bus meddelandesessioner en inbyggd implementering av det här mönstret.
Följande diagram visar det allmänna sekventiella konvojmönstret.
I kön kan meddelanden för olika kategorier interfolieras, enligt följande diagram.
Det här mönstret ger flera viktiga fördelar:
Ordnad bearbetning per grupp. Meddelanden inom varje kategori bearbetas strikt i följd, vilket förhindrar rasförhållanden, oordnade tillståndsmutationer och behovet av att ordna om lösningar.
Vågrät skalning mellan grupper. Varje kategori är en oberoende enhet för samtidighet. Att lägga till konsumenter ökar genomströmningen proportionellt mot antalet aktiva kategorier, utan att bryta mot ordningsgarantierna.
Avkoppling mellan producent och konsument. Producenter skickar meddelanden utan vetskap om vilken konsument som ska bearbeta dem eller när. Konsumenterna är oberoende skalbara och utbytbara.
Problem och överväganden
Tänk på följande när du bestämmer dig för hur du implementerar det här mönstret:
Kategori- och skalningsenhet. Ta reda på vilken egenskap för inkommande meddelanden du kan skala ut på. Kategorinyckeln definierar parallellitetsenheten: varje distinkt nyckelvärde blir en oberoende processbar grupp. I scenariot för orderspårning är den här egenskapen order-ID:t. Om du väljer en nyckel som är för grov (till exempel ett enda kund-ID för alla beställningar) begränsas parallelliteten, medan valet av en nyckel som är för bra inte ger meningsfulla orderfördelar.
Dataflödesgränser. Utvärdera målmeddelandets genomströmning. Eftersom det här mönstret framtvingar sekventiell bearbetning inom varje kategori begränsas dataflödet per kategori av tiden för att bearbeta ett enda meddelande. Optimera bearbetningstiden per meddelande, till exempel genom att använda asynkrona I/O- eller nedströmsskrivningar för batchbearbetning, eftersom den tiden direkt avgör det maximala dataflödet för varje kategori. Om det övergripande dataflödeskravet är mycket högt bör du överväga om det krävs strikt FIFO-beställning för hela meddelandelivscykeln. Alternativen är att kräva ett start- och slutmeddelande för att avgränsa en sekvens, eller att sortera meddelanden efter tidsstämpel inom ett batchfönster och sedan skicka batchen till parallell bearbetning.
Tjänstens funktioner. Kontrollera om den meddelandeförmedlare du har valt stöder att meddelanden bearbetas ett i taget inom en kö eller en kategori i en kö. Alla meddelandetjänster tillhandahåller inte låsning på sessionsnivå eller FIFO-garantier inom en partition. Om mäklaren inte har inbyggt stöd för den här funktionen måste konsumenten implementera sin egen samordningslogik, vilket ökar komplexiteten och riskerar duplicerad bearbetning, missade meddelanden eller körning i fel ordning. Sessionsstöd kan också begränsa valet av meddelandenivå eller SKU, vilket påverkar kostnaden.
Utvecklingsbarhet. Planera hur du ska lägga till nya kategorier av meddelanden i systemet. Mönstret måste kunna hantera en ökning av kategorikardinaliteten utan att kräva strukturella förändringar hos konsumenterna. Anta till exempel att transaktionssystemet som beskrevs tidigare är specifikt för en kund. Om du behöver registrera en ny kund bör du kunna lägga till en uppsättning transaktionsregisterprocessorer som distribuerar arbete per kund-ID utan att göra om kötopologin.
Leverans av meddelanden i fel ordning. Meddelanden kan komma i fel ordning på grund av varierande nätverksfördröjning mellan producenten och förmedlaren, innan förmedlarens sessionsordning börjar gälla. Överväg att använda sekvensnummer för att verifiera ordningen inom varje kategori. Du kan också inkludera en slutsekvensflagga i det sista meddelandet i en transaktion så att konsumenterna kan identifiera när en sekvens är klar.
Hantering av giftmeddelanden. Ett meddelande som upprepade gånger misslyckas med bearbetning inom en session blockerar alla efterföljande meddelanden i sessionen eftersom mönstret tillämpar strikt sekventiell ordning. Utforma en strategi för att upptäcka giftmeddelanden, till exempel genom att spåra antalet leveransförsök, och flytta dem till en kö för obeställbara meddelanden när ett definierat gränsvärde för antal återförsök har uppnåtts, så att de återstående meddelandena i sessionen kan fortsätta att bearbetas.
Brokertillgänglighet. Meddelandeförmedlaren är ett gemensamt beroende för alla kategorier. Dess tillgänglighet och hållbarhet påverkar direkt mönstrets tillförlitlighetsgarantier. Utvärdera resiliensfunktioner på brokernivå, till exempel tillgänglighetszoner och geografisk haveriåterställning, utifrån arbetsbelastningens tillgänglighetskrav och budget, eftersom konfigurationer med högre feltålighet vanligtvis ökar kostnaden.
Producentnyckelns korrekthet. Mönstret förutsätter att producenterna anger kategorinyckeln (sessions-ID) korrekt för varje meddelande. Om en producent anger en felaktig nyckel, antingen av misstag eller på grund av en bugg, dirigeras meddelandet till fel session och skadar gruppens tillstånd. Verifiera att producenter tilldelar kategorinycklar konsekvent och överväg att lägga till nyckelvalideringslogik hos konsumenten om konsekvensen av ett felaktigt meddelande är allvarlig.
Driftkomplexitet. Övervakning av sessionsbaserad bearbetning lägger till driftkostnader som överstiger standardköförbrukningen. Operatörer behöver insyn i kvarvarande sessionsloggar (antalet aktiva sessioner och djupet av meddelanden som väntar i varje session) för att identifiera kategorier som ligger efter. Sessioner med obeställbara meddelanden kräver ett separat arbetsflöde för övervakning och reparation för att undersöka misslyckade meddelanden, lösa rotorsaken och spela upp korrigerade meddelanden tillbaka till sessionen.
Låskonflikter och latens för sessionslås. Sessionslåsning medför svarstidskostnader eftersom varje konsument måste skaffa ett exklusivt lås på en session innan meddelanden bearbetas. När en konsument har ett sessionslås kan ingen annan konsument bearbeta meddelanden från den sessionen, även om konsumenten är långsam eller tillfälligt stoppad. Om låsvaraktigheten är för kort kan låset löpa ut, vilket leder till att meddelanden bearbetas om. Om låstiden är för lång, fördröjer en konsument som har fastnat återställningen. Justera sessionslåsets varaktighet utifrån den förväntade bearbetningstiden för meddelanden och implementera låsförnyelse för långvariga åtgärder.
Konsumentskalning och kostnad. Parallellism mellan sessioner motsvarar samtidiga konsumentinstanser. I en serverlös modell som Azure Functions mappar varje aktiv session till en samtidig körning, och i en dedikerad modell mappas den till en instans eller tråd. Antalet aktiva sessioner påverkar därför beräkningskostnaden direkt. Planera skalningsgränser för konsumenter och samtidighetskontroller för att balansera genomströmning i förhållande till kostnad.
När du ska använda det här mönstret
Använd det här mönstret i sådana här scenarier:
- Meddelanden anländer i ordning och måste bearbetas i samma ordning.
- Meddelanden kan kategoriseras så att varje kategori blir en oberoende skalningsenhet för systemet.
Det här mönstret kanske inte är lämpligt när:
Du förväntar dig extremt höga dataflödesscenarier (miljontals meddelanden per minut), eftersom FIFO-kravet begränsar den skalning som systemet kan uppnå.
Meddelandenas ordning krävs inte. När meddelanden kan bearbetas oberoende av varandra i valfri ordning ger mönstret Konkurrerande konsumenter enklare horisontell skalning utan samordningskostnaderna för sessionslåsning.
Design av arbetsbelastning
Utvärdera hur Sequential Convoy kan användas i utformningen av en arbetsbelastning för att uppfylla de mål och principer som behandlas i Azure Well-Architected Framework-pelarna. 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 använder sessionsbaserad FIFO-beställning för att eliminera konkurrensförhållanden, konkurrensbenägen meddelandehanteringslogik och andra lösningar för felaktigt ordnade meddelanden som kan leda till fel. - RE:02 Kritiska flöden - RE:07 Bakgrundsjobb |
Om detta mönster inför kompromisser inom en pelare bör du överväga dem mot målen för de andra pelarna.
Example
På Azure kan du implementera det här mönstret med hjälp av Service Bus meddelandesessioner. För konsumenter kan du använda antingen Azure Logic Apps med Service Bus-peek-lock-kopplingen eller Azure Functions med Service Bus-utlösaren.
När en producent anger SessionId egenskapen för ett meddelande grupperar Service Bus alla meddelanden som delar samma sessions-ID i en enda logisk session. En konsument accepterar en session och får ett exklusivt lås på den. Det här låset garanterar att endast en konsument bearbetar meddelanden för den sessionen när som helst och att meddelanden tas emot i FIFO-ordning. Andra konsumenter kan samtidigt acceptera och bearbeta olika sessioner, vilket ger parallellt dataflöde mellan grupper.
I orderspårningsexemplet bearbetar systemet varje transaktionsregistermeddelande i den ordning det tas emot och skickar varje transaktion till en annan kö där kategorin är inställd på order-ID. En transaktion omfattar aldrig flera ordrar i det här scenariot, så bearbetar konsumenterna varje kategori parallellt men i FIFO-ordning inom kategorin.
Transaktionsregisterprocessorn fläktar ut meddelandena genom att de-batcha innehållet i varje meddelande i den första kön:
Transaktionsregisterprocessorn utför tre steg:
- Går igenom huvudboken en transaktion i taget.
- Anger sessions-ID för meddelandet så att det matchar order-ID:t.
- Skickar varje transaktion i transaktionsregistret till en sekundär kö med sessions-ID inställt på order-ID: t.
Konsumenterna lyssnar på den sekundära kön och bearbetar alla meddelanden med matchande order-ID i FIFO-ordning. Konsumenter använder peek-lock-läge .
Transaktionsköen är en seriell till parallell övergångspunkt: alla transaktioner passerar genom den sekventiellt innan de går ut till sessionsbaserad parallell bearbetning. Det här serialiseringssteget är den främsta skalbarhetsflaskhalsen eftersom det begränsar genomströmningen i hela den efterföljande pipelinekedjan. Men efter att huvudboksprocessorn har skickat ut meddelanden till den sekundära kön kan konsumenterna skalas oberoende mellan sessioner, en per order-ID.
Stödjande teknologier
Service Bus meddelandesessioner: Grupperar meddelanden efter sessions-ID och framtvingar FIFO-bearbetning inom varje session. Meddelandesessioner är den primära Azure mekanismen för att implementera mönstret Sekventiell konvoj.
Azure Functions Service Bus utlösare: Stöder sessionsbaserade utlösare som gör att funktionsinstanser kan bearbeta meddelanden från en enskild session i taget.
Logic Apps Service Bus-koppling: Tillhandahåller en Service Bus-koppling med stöd för peek-lock för att använda sessionsaktiverade köer i arbetsflödesbaserad bearbetning.
Bidragsgivare
Microsoft ansvarar för den här artikeln. Följande bidragsgivare skrev den här artikeln.
Huvudförfattare:
- Naga Venkata Cheruvu | Senior lösningsarkitekt för molntjänster + AI-infrastruktur
Om du vill se linkedin-profiler som inte är offentliga loggar du in på LinkedIn.
Relaterade resurser
Mönster för konkurrerande konsumenter: Flera konsumenter hämtar meddelanden från en delad kö parallellt, vilket ökar dataflödet men tar bort ordergarantier per meddelande. Mönstret Sequential Convoy åtgärdar det ordningsgap som Competing Consumers ger upphov till. Den åtgärdar det här gapet genom att partitionera meddelanden i kategorinyckelsessioner och bearbeta varje session sekventiellt.
Köbaserat mönster för belastningsutjämning: En kö buffrar arbete mellan producenter och konsumenter för att absorbera belastningstoppar och jämna ut varierande belastning. Sequential Convoy-mönstret bygger vidare på denna buffring genom att lägga till sessionsbaserad partitionering, så att kön både balanserar belastningen mellan kategorier och bevarar FIFO-ordningen inom varje kategori.
Mönster för prioritetskö: Meddelanden dirigeras till separata köer eller ges prioritet i en kö så att arbete med högre prioritet bearbetas före arbete med lägre prioritet. När beställning inom en prioritetsnivå också måste bevaras kan mönstret Sekventiell konvoj kombineras med prioritetsköer för att framtvinga FIFO-bearbetning inom varje prioriterad session.
Peek-Lock-meddelande (icke-destruktiv läsning): Denna åtgärd hämtar och låser atomiskt ett meddelande från en kö eller prenumeration för bearbetning.
För leverans av korrelerade meddelanden i Logic Apps med hjälp av Service Bus sessioner: Det här blogginlägget beskriver Logic Apps-stöd för sekventiell konvojmönster.