Koreografimönster

Azure Event Grid
Azure Service Bus

Låt varje komponent i systemet delta i beslutsprocessen om arbetsflödet för en affärstransaktion i stället för att förlita sig på en central kontrollpunkt.

Kontext och problem

I arkitekturen för mikrotjänster är det ofta så att ett molnbaserat program är indelat i flera små tjänster som arbetar tillsammans för att bearbeta en affärstransaktion från slutpunkt till slutpunkt. För att minska kopplingen mellan tjänster ansvarar varje tjänst för en enda affärsåtgärd. Vissa fördelar är snabbare utveckling, mindre kodbas och skalbarhet. Att utforma ett effektivt och skalbart arbetsflöde är dock en utmaning och kräver ofta komplex kommunikation mellan tjänster.

Tjänsterna kommunicerar med varandra med hjälp av väldefinierade API:er. Även en enskild affärsåtgärd kan resultera i flera punkt-till-punkt-anrop mellan alla tjänster. Ett vanligt mönster för kommunikation är att använda en centraliserad tjänst som fungerar som orkestrerare. Den bekräftar alla inkommande begäranden och delegerar åtgärder till respektive tjänster. På så sätt hanterar den även arbetsflödet för hela affärstransaktionen. Varje tjänst slutför bara en åtgärd och känner inte till det övergripande arbetsflödet.

Orchestrator-mönstret minskar punkt-till-punkt-kommunikationen mellan tjänster men har vissa nackdelar på grund av den snäva kopplingen mellan orkestratorn och andra tjänster som deltar i bearbetningen av affärstransaktionen. För att kunna utföra uppgifter i en sekvens måste orkestreraren ha viss domänkunskap om ansvarsområdena för dessa tjänster. Om du vill lägga till eller ta bort tjänster bryts befintlig logik och du måste koppla om delar av kommunikationsvägen. Du kan konfigurera arbetsflödet, lägga till eller ta bort tjänster enkelt med en väldesignad orkestrerare, men en sådan implementering är komplex och svår att underhålla.

Bearbeta en begäran med hjälp av en central orkestrerare

Lösning

Låt varje tjänst bestämma när och hur en affärsåtgärd bearbetas i stället för att vara beroende av en central initierare.

Ett sätt att implementera koreografi är att använda det asynkrona meddelandemönstret för att samordna verksamheten.

Bearbeta en begäran med hjälp av en koreograf

En klientbegäran publicerar meddelanden till en meddelandekö. När meddelanden kommer skickas de till prenumeranter eller tjänster som är intresserade av det meddelandet. Varje prenumerationstjänst utför sin åtgärd enligt meddelandet och svarar på meddelandekön med åtgärden lyckades eller misslyckades. Om det lyckas kan tjänsten skicka tillbaka ett meddelande till samma kö eller en annan meddelandekö så att en annan tjänst kan fortsätta arbetsflödet om det behövs. Om en åtgärd misslyckas kan meddelandebussen försöka utföra åtgärden igen.

På så sätt koreograferas arbetsflödet sinsemellan utan att vara beroende av en orkestrerare eller ha direkt kommunikation mellan dem.

Eftersom det inte finns punkt-till-punkt-kommunikation hjälper det här mönstret till att minska kopplingen mellan tjänster. Dessutom kan den ta bort prestandaflaskhalsen som orsakas av orkestratorn när den måste hantera alla transaktioner.

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

Använd koreografimönstret om du förväntar dig att uppdatera eller ersätta tjänster ofta och lägga till eller ta bort vissa tjänster så småningom. Hela appen kan ändras med mindre ansträngning och minimala avbrott i befintliga tjänster.

Tänk på det här mönstret om du upplever flaskhalsar i den centrala orkestratorn.

Det här mönstret är en naturlig modell för den serverlösa arkitekturen där alla tjänster kan vara kortvariga eller händelsedrivna. Tjänster kan startas på grund av en händelse, utföra sin uppgift och tas bort när aktiviteten är klar.

Problem och överväganden

Att decentralisera orkestreraren kan orsaka problem vid hantering av arbetsflödet.

Om en tjänst inte kan slutföra en affärsåtgärd kan det vara svårt att återställa från det felet. Ett sätt är att låta tjänsten indikera fel genom att starta en händelse. En annan tjänst prenumererar på dessa misslyckade händelser vidtar nödvändiga åtgärder, till exempel att tillämpa kompenserande transaktioner för att ångra lyckade åtgärder i en begäran. Den misslyckade tjänsten kan också misslyckas med att utlösa en händelse för felet. I så fall bör du överväga att använda en mekanism för återförsök och timeout för att identifiera åtgärden som ett fel. Ett exempel finns i avsnittet Exempel .

Det är enkelt att implementera ett arbetsflöde när du vill bearbeta oberoende affärsverksamhet parallellt. Du kan använda en enda meddelandebuss. Arbetsflödet kan dock bli komplicerat när koreografin behöver ske i en sekvens. Till exempel kan Service C starta sin åtgärd först när Service A och Service B har slutfört sina åtgärder med framgång. En metod är att ha flera meddelandebussar eller köer som får meddelanden i den ordning som krävs. Mer information finns i avsnittet Exempel .

Koreografimönstret blir en utmaning om antalet tjänster växer snabbt. Med tanke på det stora antalet oberoende rörliga delar tenderar arbetsflödet mellan tjänster att bli komplext. Dessutom blir distribuerad spårning svårt.

Orchestrator hanterar arbetsflödets återhämtning centralt och kan bli en enskild felpunkt. Å andra sidan, för koreografi, fördelas rollen mellan alla tjänster och återhämtning blir mindre robust.

Varje tjänst ansvarar inte bara för återhämtning av åtgärden utan även för arbetsflödet. Det här ansvaret kan vara betungande för tjänsten och svår att implementera. Varje tjänst måste försöka igen tillfälliga, icke-övergående och timeout-fel, så att begäran avslutas korrekt om det behövs. Tjänsten måste också vara noggrann med att kommunicera åtgärdens framgång eller misslyckande så att andra tjänster kan agera i enlighet med detta.

Design av arbetsbelastning

En arkitekt bör utvärdera hur koreografimönstret kan användas i arbetsbelastningens design för att uppfylla de mål och principer som beskrivs i grundpelarna i Azure Well-Architected Framework. Till exempel:

Grundpelare Så här stöder det här mönstret pelarmål
Operational Excellence hjälper till att leverera arbetsbelastningskvalitet genom standardiserade processer och teamsammanhållning. Eftersom de distribuerade komponenterna i det här mönstret är autonoma och utformade för att vara utbytbara kan du ändra arbetsbelastningen med mindre övergripande ändringar i systemet.

- OE:04 Verktyg och processer
Prestandaeffektivitet hjälper din arbetsbelastning att effektivt uppfylla kraven genom optimeringar inom skalning, data och kod. Det här mönstret är ett alternativ när prestandaflaskhalsar uppstår i en centraliserad orkestreringstopologi.

- PE:02 Kapacitetsplanering
- PE:05 Skalning och partitionering

Som med alla designbeslut bör du överväga eventuella kompromisser mot målen för de andra pelarna som kan införas med det här mönstret.

Exempel

Det här exemplet visar koreografimönstret genom att skapa en händelsedriven, molnbaserad arbetsbelastning som kör funktioner tillsammans med mikrotjänster. När en klient begär att ett paket ska levereras tilldelar arbetsbelastningen en drönare. När paketet är redo att hämtas av den schemalagda drönaren kommer leveransprocessen igång. Under överföring hanterar arbetsbelastningen leveransen tills den får den levererade statusen.

Det här exemplet är en refaktorisering av implementeringen av drönarleveransen som ersätter Orchestrator-mönstret med koreografimönstret.

Diagram över en händelsedriven molnbaserad exempelarbetsbelastning som implementerar koreografimönster

Inmatningstjänsten hanterar klientbegäranden och konverterar dem till meddelanden, inklusive leveransinformation. Affärstransaktioner initieras efter att de nya meddelandena har förbrukats.

En enskild klientaffärstransaktion kräver tre distinkta affärsåtgärder: att skapa eller uppdatera ett paket, tilldela en drönare för att leverera paketet och korrekt hantering av leveransen som består av att kontrollera och så småningom öka medvetenheten när det levereras. Tre mikrotjänster utför affärsbearbetningen: Paket-, Drone Scheduler- och Delivery-tjänster. I stället för en central orkestrerare använder tjänsterna meddelanden för att kommunicera sinsemellan. Varje tjänst ansvarar för att implementera ett protokoll i förväg som samordnar på ett decentraliserat sätt affärsarbetsflödet.

Designa

Affärstransaktionen bearbetas i en sekvens genom flera hopp. Varje hopp delar en enda meddelandebuss mellan alla affärstjänster.

När en klient skickar en leveransbegäran via en HTTP-slutpunkt tar inmatningstjänsten emot den, konverterar en sådan begäran till ett meddelande och publicerar sedan meddelandet till den delade meddelandebussen. De prenumerationsbaserade affärstjänsterna kommer att förbruka nya meddelanden som läggs till i bussen. När du tar emot meddelandet kan affärstjänsterna slutföra åtgärden med framgång, fel eller så kan begäran överskrida tidsgränsen. Om det lyckas svarar tjänsterna på bussen med statuskoden Ok, genererar ett nytt åtgärdsmeddelande och skickar det till meddelandebussen. Om det uppstår ett fel eller tidsgräns rapporterar tjänsten fel genom att skicka orsakskoden till meddelandebussen. Dessutom kommer meddelandet att vara obeställbara för senare hantering. Meddelanden som inte kunde tas emot eller bearbetas inom en rimlig och lämplig tid flyttas även DLQ.

Designen använder flera meddelandebussar för att bearbeta hela affärstransaktionen. Microsoft Azure Service Bus och Microsoft Azure Event Grid är sammansatta för att tillhandahålla meddelandetjänstplattformen för den här designen. Arbetsbelastningen distribueras på Azure Container Apps som är värd för Azure Functions för inmatning och appar som hanterar händelsedriven bearbetning som kör affärslogik.

Designen säkerställer att koreografin förekommer i en sekvens. Ett enda Azure Service Bus-namnområde innehåller ett ämne med två prenumerationer och en sessionsmedveten kö. Inmatningstjänsten publicerar meddelanden till ämnet. Pakettjänsten och Drone Scheduler-tjänsten prenumererar på ämnet och publicerar meddelanden som kommunicerar lyckade meddelanden till kön. Med en vanlig sessionsidentifierare som ett GUID som är kopplat till leveransidentifieraren möjliggör ordnad hantering av obundna sekvenser av relaterade meddelanden. Leveranstjänsten väntar på två relaterade meddelanden per transaktion. Det första meddelandet anger att paketet är redo att levereras och det andra signalerar att en drönare är schemalagd.

Den här designen använder Azure Service Bus för att hantera värdefulla meddelanden som inte kan gå förlorade eller dupliceras under hela leveransprocessen. När paketet levereras publiceras även en tillståndsändring till Azure Event Grid. I den här designen har händelsesändaren inga förväntningar på hur tillståndsändringen hanteras. Underordnade organisationstjänster som inte ingår som en del av den här designen kan lyssna på den här händelsetypen och reagera med att köra specifik affärslogik (det vill s.v.s. skicka orderstatusen via e-post till användaren).

Om du planerar att distribuera detta till en annan beräkningstjänst, till exempel AKS pub-sub pattern application boilplate, kan den implementeras med två containrar i samma podd. En container kör ambassadören som interagerar med meddelandebussen medan den andra kör affärslogik. Metoden med två containrar i samma podd förbättrar prestanda och skalbarhet. Ambassadören och företagstjänsten delar samma nätverk som möjliggör låg svarstid och högt dataflöde.

För att undvika sammanhängande återförsöksåtgärder som kan leda till flera åtgärder bör företagstjänster omedelbart flagga oacceptabla meddelanden. Det är möjligt att utöka sådana meddelanden med hjälp av välkända orsakskoder eller en definierad programkod, så att den kan flyttas till en kö med obeställbara meddelanden (DLQ). Överväg att hantera konsekvensproblem med att implementera Saga från underordnade tjänster. En annan tjänst kan till exempel endast hantera meddelanden med obeställbara meddelanden i reparationssyfte genom att utföra en kompensations-, rety- eller pivottransaktion.

Affärstjänsterna är idempotent för att se till att återförsök inte resulterar i duplicerade resurser. Pakettjänsten använder till exempel upsert-åtgärder för att lägga till data i datalagret.

Tänk på dessa mönster i din design för koreografi.