Model choreografie

Zapojte každou komponentu systému do rozhodovacího procesu týkajícího se pracovního postupu obchodní transakce a nespoléhejte na centrální bod řízení.

Kontext a problém

V architektuře mikroslužeb se často stává, že cloudová aplikace je rozdělená do několika malých služeb, které společně zpracovávají obchodní transakce od konce. Aby bylo možné snížit párování mezi službami, zodpovídá každá služba za jednu obchodní operaci. Mezi výhody patří rychlejší vývoj, menší základ kódu a škálovatelnost. Návrh efektivního a škálovatelného pracovního postupu je ale výzvou a často vyžaduje složitou komunikaci mezi službami.

Služby spolu komunikují pomocí dobře definovaných rozhraní API. Dokonce i jedna obchodní operace může vést k několika voláním typu point-to-point mezi všemi službami. Běžným vzorem komunikace je použití centralizované služby, která funguje jako orchestrátor. Potvrdí všechny příchozí požadavky a deleguje operace na příslušné služby. Přitom také spravuje pracovní postup celé obchodní transakce. Každá služba právě dokončí operaci a nemá přehled o celkovém pracovním postupu.

Model orchestrátoru snižuje komunikaci mezi službami typu point-to-point, ale má určité nevýhody kvůli úzce párování mezi orchestrátorem a jinými službami, které se podílejí na zpracování obchodní transakce. Aby bylo možné provádět úkoly v sekvenci, musí mít orchestrátor určité znalosti o zodpovědnostech těchto služeb. Pokud chcete přidat nebo odebrat služby, existující logika se přeruší a budete muset přebírat části komunikační cesty. I když můžete pracovní postup konfigurovat, snadno přidávat nebo odebírat služby pomocí dobře navrženého orchestrátoru, taková implementace je složitá a těžko se udržuje.

Zpracování požadavku pomocí centrálního orchestrátoru

Řešení

Zajistěte si nezávislost na centrálním orchestrátoru a dejte každé službě na výběr, kdy a jak se zpracuje obchodní operace.

Jedním ze způsob, jak implementovat choreografii, je použít asynchronní vzor zasílání zpráv ke koordinaci obchodních operací.

Zpracování požadavku pomocí choreografa

Požadavek klienta publikuje zprávy do fronty zpráv. Při doručení zpráv se předá odběratelům nebo službám, které o tuto zprávu mají zájem. Každá předplacená služba dělá svoji operaci podle zprávy a reaguje na frontu zpráv s úspěchem nebo neúspěchem operace. V případě úspěchu může služba odeslat zprávu zpět do stejné fronty nebo jiné fronty zpráv, aby v případě potřeby v pracovním postupu pokračovala jiná služba. Pokud operace selže, sběrnice zpráv může operaci zopakovat.

Tímto způsobem služby komunikují s pracovním postupem mezi sebou, aniž by závisejí na orchestrátoru nebo přímé komunikaci mezi nimi.

Vzhledem k tomu, že neexistuje komunikace typu point-to-point, tento model pomáhá omezit párování mezi službami. Může také odstranit kritický bod výkonu způsobený orchestrátorem, když musí řešit všechny transakce.

Kdy se má tento model použít

Pokud očekáváte, že budete často aktualizovat, odebírat nebo přidávat nové služby, použijte vzor choreografie. Celou aplikaci je možné upravit s menším úsilím a minimálním přerušením stávajících služeb.

Tento model zvažte, pokud v centrálním orchestrátoru dochází k kritickým místům výkonu.

Tento model je přirozeným modelem bez serveru, ve kterém mohou být všechny služby krátkodobé nebo řízené událostmi. Služby se mohou z důvodu události z důvodu události z důvodu své úlohy z důvodu této události z důvodu dokončení úlohy odebrat.

Problémy a důležité informace

Decentralizace orchestrátoru může způsobit problémy při správě pracovního postupu.

Pokud se službě nepodaří dokončit obchodní operaci, může být obtížné zotavit se z tohoto selhání. Jednou z nich je to, že služba indikuje selhání aktivací události. Jiná služba, která se přihlásí k odběru těchto neúspěšných událostí, přijímá nezbytné akce, jako je použití kompenzačních transakcí k vrácení úspěšných operací v požadavku. Neúspěšná služba může také v případě selhání selhat při spuštění události. V takovém případě zvažte použití mechanismu opakování nebo časového limitu, abyste operaci rozpoznali jako selhání. Příklad najdete v části Příklad.

Pokud chcete zpracovávat nezávislé obchodní operace paralelně, je jednoduché implementovat pracovní postup. Můžete použít jednu sběrnici zpráv. Pracovní postup se ale může zkomplikovat, když se v sekvenci musí vyskytnout choreografie. Služba C může například spustit svoji operaci až poté, co služba A a služba B úspěšně dokončí své operace. Jedním z přístupů je mít více sběrných zpráv, které dosílat zprávy v požadovaném pořadí. Další informace najdete v části Příklad.

Vzor choreografie se stává výzvou, pokud počet služeb rychle roste. Vzhledem k vysokému počtu nezávislých pohyblivých částí je pracovní postup mezi službami často složitý. Distribuované trasování je také obtížné.

Orchestrátor centrálně spravuje odolnost pracovního postupu a může se stát jediným bodem selhání. V případě choreografie je ale role rozdělená mezi všechny služby a odolnost proti chybám je méně robustní.

Každá služba nezo zodpovídá nejen za odolnost své operace, ale také za pracovní postup. Tato odpovědnost může být pro službu zatěžující a implementace může být obtížná. Každá služba musí opakovat přechodná, nepřenosná selhání a selhání časového limitu, aby se v případě potřeby žádost řádně ukončila. Služba také musí být usilovná při komunikaci o úspěchu nebo neúspěchu operace, aby podle toho šly fungovat i jiné služby.

Příklad

Tento příklad ukazuje model choreografie s aplikací pro doručování pomocí dronů. Když klient požádá o vyzvednutí, aplikace přiřadí dron a upozorní ho.

GitHub loga Příklad tohoto modelu je k dispozici na GitHub.

Zblízka automaticky vygenerovaný popis mapy

Jedna klientská obchodní transakce vyžaduje tři různé obchodní operace: vytvoření nebo aktualizaci balíčku, přiřazení dronu pro doručení balíčku a kontrolu stavu doručení. Tyto operace jsou prováděny třemi mikroslužbami: balíčkem, plánovačem dronů a službami doručování. Místo centrálního orchestrátoru služby používají zasílání zpráv ke spolupráci a koordinaci žádosti mezi sebou.

Návrh

Obchodní transakce se zpracovává v sekvenci prostřednictvím několika segmentů směrování. Každý segment směrování má sběrnici zpráv a příslušnou obchodní službu.

Když klient odešle žádost o doručení prostřednictvím koncového bodu HTTP, služba ingestování ji přijme, vyvolá událost operace a odešle ji do sběrnice zpráv. Sběrnice vyvolá předplacenou obchodní službu a odešle událost v požadavku POST. Při přijetí události může obchodní služba dokončit operaci s úspěchem, neúspěchem nebo časovým limitem požadavku. V případě úspěchu služba odpoví sběrnici pomocí stavového kódu OK, vyvolá novou událost operace a odešle ji do sběrnice zpráv dalšího segmentu směrování. V případě selhání nebo časového limitu služba hlásí chybu odesláním kódu BadRequest do sběrnice zpráv, která odeslala původní požadavek POST. Sběrnice zpráv zopakuje operaci na základě zásady opakování. Po uplynutí této doby sběrnice zpráv označí neúspěšnou operaci a další zpracování celého požadavku se zastaví.

Tento pracovní postup pokračuje, dokud se nezpracuje celý požadavek.

Návrh používá ke zpracování celé obchodní transakce více sběraných zpráv. Microsoft Azure Event Grid poskytuje službu zasílání zpráv. Aplikace je nasazená v clusteru Azure Kubernetes Service (AKS) se dvěma kontejnery ve stejném podu. V jednom kontejneru běží ambasador, který komunikuje Event Grid, zatímco druhý provozuje obchodní službu. Přístup se dvěma kontejnery ve stejném podu zlepšuje výkon a škálovatelnost. Ambasador a obchodní služba sdílejí stejnou síť, což umožňuje nízkou latenci a vysokou propustnost.

Abyste se vyhnuli kaskádovým operacím opakování, které by mohly vést k více úsilím, Event Grid místo obchodní služby opakovat operaci. Označí neúspěšný požadavek příznakem odesláním zprávy do fronty nedoručených zpráv (DLQ).

Obchodní služby jsou idempotentní, aby se ujistěte, že operace opakování nesníží duplicitní prostředky. Například služba Package používá operace upsert k přidání dat do úložiště dat.

Příklad implementuje vlastní řešení pro korelaci volání napříč všemi službami a Event Grid segmenty směrování.

Tady je příklad kódu, který ukazuje vzor choreografie mezi všemi obchodními službami. Zobrazuje pracovní postup transakcí aplikace pro doručování pomocí dronů. Kód pro zpracování a protokolování výjimek byl kvůli stručnosti odebrán.

[HttpPost]
[Route("/api/[controller]/operation")]
[ProducesResponseType(typeof(void), 200)]
[ProducesResponseType(typeof(void), 400)]
[ProducesResponseType(typeof(void), 500)]

public async Task<IActionResult> Post([FromBody] EventGridEvent[] events)
{

   if (events == null)
   {
       return BadRequest("No Event for Choreography");
   }

   foreach(var e in events)
   {

        List<EventGridEvent> listEvents = new List<EventGridEvent>();
        e.Topic = eventRepository.GetTopic();
        e.EventTime = DateTime.Now;
        switch (e.EventType)
        {
            case Operations.ChoreographyOperation.ScheduleDelivery:
            {
                var packageGen = await packageServiceCaller.UpsertPackageAsync(delivery.PackageInfo).ConfigureAwait(false);
                if (packageGen is null)
                {
                    //BadRequest allows the event to be reprocessed by Event Grid
                    return BadRequest("Package creation failed.");
                }

                //we set the event type to the next choreography step
                e.EventType = Operations.ChoreographyOperation.CreatePackage;
                listEvents.Add(e);
                await eventRepository.SendEventAsync(listEvents);
                return Ok("Created Package Completed");
            }
            case Operations.ChoreographyOperation.CreatePackage:
            {
                var droneId = await droneSchedulerServiceCaller.GetDroneIdAsync(delivery).ConfigureAwait(false);
                if (droneId is null)
                {
                    //BadRequest allows the event to be reprocessed by Event Grid
                    return BadRequest("could not get a drone id");
                }
                e.Subject = droneId;
                e.EventType = Operations.ChoreographyOperation.GetDrone;
                listEvents.Add(e);
                await eventRepository.SendEventAsync(listEvents);
                return Ok("Drone Completed");
            }
            case Operations.ChoreographyOperation.GetDrone:
            {
                var deliverySchedule = await deliveryServiceCaller.ScheduleDeliveryAsync(delivery, e.Subject);
                return Ok("Delivery Completed");
            }
            return BadRequest();
    }
}

Vezměte v úvahu tyto vzory ve svém návrhu pro choreografii.