Building Domain Driven Microservices

Chandra Ramalingam

Sledovat

1. července, 2020 – 18 minut čtení

Image credits:

Výraz „micro“ ve slově Microservices sice označuje velikost služby, ale není jediným kritériem, které z aplikace dělá mikroslužbu. Když týmy přecházejí na architekturu založenou na mikroslužbách, usilují o zvýšení své agility – autonomní a časté nasazování funkcí. Je těžké stanovit jedinou stručnou definici tohoto architektonického stylu. Líbila se mi tato krátká definice od Adriana Cockcrofta – „architektura orientovaná na služby složená z volně spřažených prvků, které mají ohraničené kontexty.“

Ačkoli tato definice definuje heuristiku návrhu na vysoké úrovni, architektura mikroslužeb má některé jedinečné vlastnosti, které ji odlišují od architektury orientované na služby z minulých let. Několik z těchto charakteristik uvádíme níže. Tyto a několik dalších jsou dobře zdokumentovány – za všechny jmenujme článek Martina Fowlera a knihu Building Microservices od Sama Newmana.

  1. Služby mají dobře definované hranice soustředěné kolem obchodního kontextu, a ne kolem libovolných technických abstrakcí
  2. Skrývají implementační detaily a vystavují funkčnost prostřednictvím rozhraní odhalujících záměr
  3. Služby nesdílejí své vnitřní struktury za svými hranicemi. Například žádné sdílení databází.
  4. Služby jsou odolné vůči selháním.
  5. Týmy vlastní své funkce nezávisle a mají možnost samostatně vydávat změny
  6. Týmy přijímají kulturu automatizace. Například automatizované testování, nepřetržitá integrace a nepřetržité dodávání

V krátkosti můžeme tento styl architektury shrnout takto:

Volně vázaná architektura orientovaná na služby, kde je každá služba uzavřena v přesně definovaném ohraničeném kontextu, což umožňuje rychlé, časté a spolehlivé dodávání aplikací.

Návrh řízený doménou a ohraničené kontexty

Síla mikroslužeb vychází z jasného vymezení jejich odpovědnosti a vymezení hranic mezi nimi. Účelem je zde vybudovat vysokou soudržnost uvnitř hranice a nízkou provázanost mimo ni. To znamená, že věci, které mají tendenci se měnit společně, by měly patřit k sobě. Stejně jako v mnoha reálných problémech se to snáze řekne, než udělá – podniky se vyvíjejí a předpoklady se mění. Proto je schopnost refaktorizace další kritickou věcí, kterou je třeba při návrhu systémů zvážit.

Doménou řízený návrh (DDD) je klíčovým a podle našeho názoru nezbytným nástrojem při návrhu mikroslužeb, ať už jde o rozbití monolitu nebo implementaci projektu na zelené louce. Doménou řízený návrh, který proslavil Eric Evans svou knihou , je soubor myšlenek, principů a vzorů, které pomáhají navrhovat softwarové systémy na základě základního modelu obchodní domény. Vývojáři a doménoví experti spolupracují na vytváření obchodních modelů ve všudypřítomném společném jazyce. Tyto modely pak vážou na systémy, kde mají smysl, vytvářejí protokoly spolupráce mezi těmito systémy a týmy, které na těchto službách pracují. A co je ještě důležitější, navrhují koncepční obrysy nebo hranice mezi systémy.

Návrh mikroslužeb čerpá inspiraci z těchto konceptů, protože všechny tyto principy pomáhají vytvářet modulární systémy, které se mohou měnit a vyvíjet nezávisle na sobě.

Než budeme pokračovat dále, projděme si v rychlosti některé základní pojmy DDD. Úplný přehled návrhu řízeného doménou je mimo rámec tohoto blogu. Všem, kteří se snaží vytvářet mikroslužby, vřele doporučujeme knihu Erica Evanse

Domain: Doména: Představuje to, čím se organizace zabývá. V níže uvedeném příkladu by to byl maloobchod nebo elektronický obchod.

Subdoména: Organizace nebo obchodní jednotka v rámci organizace. Doména se skládá z více subdomén.

Všudypřítomný jazyk: Jedná se o jazyk používaný k vyjádření modelů. V níže uvedeném příkladu je položka Model, která patří do všudypřítomného jazyka každé z těchto subdomén. Vývojáři, produktoví manažeři, doménoví experti a obchodní zainteresované strany se dohodnou na stejném jazyce a používají ho ve svých artefaktech – kódu, dokumentaci k produktu atd.

Obrázek 1: Vývojáři, produktoví manažeři, doménoví experti a obchodní zainteresované strany se dohodnou na stejném jazyce a používají ho ve svých artefaktech – kódu, dokumentaci k produktu atd. Subdomény a ohraničené kontexty v doméně elektronického obchodu

Ohraničené kontexty: Doménově řízený návrh definuje Vázané kontexty jako „prostředí, ve kterém se slovo nebo výrok objevuje a které určuje jeho význam“. Stručně řečeno to znamená hranici, v jejímž rámci má model smysl. Ve výše uvedeném příkladu nabývá slovo „Item“ v každém z těchto kontextů jiného významu. V kontextu Katalogu znamená Položka prodávaný výrobek, zatímco v kontextu Košíku znamená položku, kterou si zákazník přidal do košíku. V kontextu Fulfillment znamená položku ve skladu, která bude odeslána zákazníkovi. Každý z těchto modelů je jiný a každý má jiný význam a případně obsahuje jiné atributy. Oddělením a izolací těchto modelů v rámci jejich příslušných ohraničení můžeme tyto modely vyjádřit volně a bez dvojznačnosti.

Poznámka: Je nezbytné pochopit rozdíl mezi subdoménami a ohraničenými kontexty. Subdoména patří do prostoru problému, tj. jak váš podnik vidí problém, zatímco Vázané kontexty patří do prostoru řešení, tj. jak budeme řešení problému realizovat. Teoreticky může mít každá subdoména více ohraničených kontextů, ačkoli my usilujeme o jeden ohraničený kontext na subdoménu.

Jak souvisí mikroslužby s ohraničenými kontexty

Kam tedy mikroslužby patří? Dá se říci, že každý ohraničený kontext odpovídá jedné mikroslužbě? Ano i ne. Uvidíme, proč tomu tak je. Mohou nastat případy, kdy je hranice nebo obrys vašeho ohraničeného kontextu poměrně velký.

Obrázek 2: Hranice nebo obrys ohraničeného kontextu je poměrně velký. Ohraničený kontext a mikroslužby

Podívejte se na výše uvedený příklad. Vázaný kontext Ceny má tři různé modely – Cena, Oceněné položky a Slevy, z nichž každý odpovídá za cenu katalogové položky, výpočet celkové ceny seznamu položek, respektive za uplatnění slev. Mohli bychom vytvořit jediný systém, který by zahrnoval všechny výše uvedené modely, ale to by se mohlo stát nesmyslně velkou aplikací. Každý z datových modelů, jak již bylo zmíněno, má své invarianty a obchodní pravidla. Pokud si nedáme pozor, časem by se ze systému mohla stát Velká blátivá koule s nejasnými hranicemi, překrývajícími se odpovědnostmi a pravděpodobně bychom se vrátili tam, kde jsme začali – k monolitu.

Jiným způsobem, jak tento systém modelovat, je oddělit nebo seskupit související modely do samostatných mikroslužeb. V DDD se tyto modely – Cena, Cenové položky a Slevy – nazývají Agregáty. Agregát je samostatný model, který skládá související modely. Stav agregátu můžete měnit pouze prostřednictvím zveřejněného rozhraní a agregát zajišťuje konzistenci a to, že invarianty platí.

Formálně je Agregát shluk souvisejících objektů, se kterými se zachází jako s jednotkou pro změny dat. Externí odkazy jsou omezeny na jednoho člena AGREGÁTU, označeného jako kořen. V rámci hranic AGGREGATE platí soubor pravidel konzistence.

Obrázek 3. Mikroslužby v cenovém kontextu

Znovu platí, že není nutné modelovat každý agregát jako samostatnou mikroslužbu. Ukázalo se to tak u služeb (agregátů) na obr. 3, ale není to nutně pravidlem. V některých případech může mít smysl umístit více agregátů do jedné služby, zejména pokud plně nerozumíme obchodní doméně. Důležité je si uvědomit, že konzistenci lze zaručit pouze v rámci jednoho agregátu a agregáty lze měnit pouze prostřednictvím publikovaného rozhraní. Jakékoli jejich porušení s sebou nese riziko, že se promění ve velkou kouli bláta.

Kontextové mapy – způsob, jak vytyčit přesné hranice mikroslužeb

Další nezbytnou sadou nástrojů ve vašem arzenálu je koncept kontextových map – opět z Domain Driven Design. Monolit se obvykle skládá z různorodých modelů, většinou těsně provázaných – modely možná znají intimní detaily jeden o druhém, změna jednoho může způsobit vedlejší účinky na jiný atd. Při rozpadu monolitu je nezbytné identifikovat tyto modely – v tomto případě agregáty – a jejich vztahy. Právě s tím nám pomáhají kontextové mapy. Slouží k identifikaci a definování vztahů mezi různými ohraničenými kontexty a agregáty. Zatímco ohraničené kontexty definují hranice modelu – Cena, Slevy atd. ve výše uvedeném příkladu, kontextové mapy definují vztahy mezi těmito modely a mezi různými kontexty. Po určení těchto závislostí můžeme určit správný model spolupráce mezi týmy, které budou tyto služby implementovat.

Úplné prozkoumání kontextových map přesahuje rámec tohoto blogu, ale budeme jej ilustrovat na příkladu. Níže uvedený diagram představuje různé aplikace, které zpracovávají platby za objednávku v elektronickém obchodě.

  1. Kontext košíku se stará o online autorizaci objednávky; Kontext objednávky zpracovává platební procesy po splnění objednávky, jako je Vypořádání; Kontaktní centrum zpracovává případné výjimky, jako je opakování platby a změna způsobu platby použitého pro objednávku
  2. Pro zjednodušení předpokládejme, že všechny tyto kontexty jsou implementovány jako samostatné služby
  3. Všechny tyto kontexty zapouzdřují stejný model.
  4. Všimněte si, že tyto modely jsou logicky stejné. To znamená, že se všechny řídí stejným jazykem všudypřítomné domény – platební metody, autorizace a zúčtování. Jen jsou součástí různých kontextů.

Dalším znakem toho, že stejný model je rozprostřen v různých kontextech, je to, že se všechny přímo integrují s jedinou platební bránou a provádějí stejné operace jako ostatní

Obrázek 4. Nesprávně definovaná mapa kontextů

Přesné vymezení hranic služeb – namapování agregátů na správné kontexty

Ve výše uvedeném návrhu (obr. 4) je velmi patrných několik problémů. Agregát plateb je součástí více kontextů. Je nemožné vynutit invarianty a konzistenci napříč různými službami, nemluvě o problémech se souběžností mezi těmito službami. Co se například stane, když kontaktní centrum změní platební metodu spojenou s objednávkou, zatímco služba Objednávky se snaží zaúčtovat vypořádání dříve zadané platební metody. Všimněte si také, že jakákoli změna platební brány by si vynutila změny ve více službách a potenciálně i v mnoha týmech, protože tyto kontexty by mohly vlastnit různé skupiny.

Po několika úpravách a zarovnání agregátů na správné kontexty získáme mnohem lepší zobrazení těchto subdomén – obr. 5. Je toho hodně, co se změnilo. Projděme si změny:

  1. Agregát Platby má nový domov – Platební služba. Tato služba také abstrahuje Platební bránu od ostatních služeb, které vyžadují platební služby. Protože nyní vlastní agregát jediný ohraničený kontext, lze snadno spravovat invarianty; všechny transakce se odehrávají v rámci jedné hranice služby, což pomáhá vyhnout se problémům se souběhem.
  2. Agregát plateb používá vrstvu ACL (Anti-corruption Layer), aby izoloval model jádra domény od datového modelu platební brány, který je obvykle poskytovatelem třetí strany a možná se bude měnit. Do návrhu aplikace takové služby pomocí vzoru Porty a adaptéry se hlouběji ponoříme v některém z příštích příspěvků. Vrstva ACL obvykle obsahuje adaptéry, které transformují datový model platební brány na agregovaný datový model služby Platby.
  3. Služba košíku volá službu Platby prostřednictvím přímých volání API, protože služba košíku může mít za úkol dokončit autorizaci platby, zatímco jsou zákazníci na webu
  4. Všimněte si interakce mezi službami Objednávky a Platby. Služba Objednávky vysílá událost domény (více o tom později v tomto blogu). Služba Platby naslouchá této události a dokončí vypořádání objednávky
  5. Služba kontaktního centra může mít mnoho agregátů, ale nás pro tento případ použití zajímá pouze agregát Objednávky. Tato služba vysílá událost při změně způsobu platby a služba Platby na ni reaguje tak, že zruší dříve použitou platební kartu a zpracuje novou platební kartu.

Obrázek 5. Redefinovaná kontextová mapa

Obvykle má monolitická nebo starší aplikace mnoho agregátů, často s překrývajícími se hranicemi. Vytvoření kontextové mapy těchto agregátů a jejich závislostí nám pomůže pochopit obrysy případných nových mikroslužeb, které z těchto monolitů vymaníme. Pamatujte, že úspěch či neúspěch architektury mikroslužeb závisí na nízké provázanosti mezi agregáty a vysoké soudržnosti uvnitř těchto agregátů.

Je také důležité si uvědomit, že ohraničené kontexty jsou samy o sobě vhodnými soudržnými jednotkami. I když má kontext více agregátů, může být celý kontext spolu s jeho agregáty složen do jediné mikroslužby. Tuto heuristiku považujeme za užitečnou zejména u domén, které jsou poněkud nepřehledné – vzpomeňte si na nový obor podnikání, do kterého se organizace pouští. Nemusíte mít dostatečný přehled o správných hranicích oddělení a jakýkoli předčasný rozklad agregátů může vést k nákladnému refaktoringu. Představte si, že musíme sloučit dvě databáze do jedné spolu s migrací dat, protože jsme náhodou zjistili, že dva agregáty patří k sobě. Zajistěte však, aby tyto agregáty byly dostatečně izolovány prostřednictvím rozhraní, aby o sobě navzájem neznaly složité detaily.

Event Storming – další technika pro identifikaci hranic služeb

Event Storming je další zásadní technikou pro identifikaci agregátů (a tedy i mikroslužeb) v systému. Je to užitečný nástroj jak pro rozbití monolitů, tak při návrhu komplexního ekosystému mikroslužeb. Tuto techniku jsme použili k rozbití jedné z našich komplexních aplikací a naše zkušenosti s Event Stormingem hodláme popsat v samostatném blogu. Pro rozsah tohoto blogu chceme poskytnout rychlý přehled na vysoké úrovni. Pokud vás zajímá další zkoumání tohoto tématu, podívejte se na video Alberta Brandelloniho.

Stručně řečeno, Event Storming je brainstormingové cvičení mezi týmy, které pracují na aplikaci – v našem případě monolitu – s cílem identifikovat různé události a procesy v doméně, které se v systému odehrávají. Týmy také identifikují agregáty nebo modely, které tyto události ovlivňují, a jejich následné dopady. Při tomto cvičení týmy identifikují různé překrývající se koncepty, nejednoznačný jazyk domény a konfliktní obchodní procesy. Seskupují související modely, nově definují agregáty a identifikují duplicitní procesy. Jak postupují v tomto cvičení, vyjasňují se ohraničené kontexty, kam tyto agregáty patří. Workshopy Event Storming jsou užitečné, pokud jsou všechny týmy v jedné místnosti – fyzické nebo virtuální – a začnou mapovat události, příkazy a procesy na tabuli ve stylu scrumu. Na konci tohoto cvičení jsou níže uvedeny obvyklé výsledky:

  1. Zdefinovaný seznam agregátů. Ty se potenciálně stanou novými mikroslužbami
  2. Doménové události, které musí proudit mezi těmito mikroslužbami
  3. Příkazy, které jsou přímými voláními od jiných aplikací nebo uživatelů

Níže jsme ukázali vzorovou tabuli na konci workshopu Event Storming. Je to skvělé cvičení pro spolupráci týmů, aby se dohodly na správných agregátech a ohraničených kontextech. Kromě toho, že je to skvělé cvičení pro budování týmu, týmy z tohoto sezení vycházejí se společným chápáním domény, všudypřítomným jazykem a přesnými hranicemi služeb.

Obrázek 6. Event Storming board

Komunikace mezi mikroslužbami

Krátce shrnuto, monolit hostí více agregátů v rámci jedné hranice procesu. Proto je možné řídit konzistenci agregátů v rámci této hranice. Například pokud zákazník zadá objednávku, můžeme snížit stav zásob položek, odeslat zákazníkovi e-mail – to vše v rámci jedné transakce. Všechny operace by byly úspěšné, nebo by všechny selhaly. Když však monolit rozbijeme a agregáty rozložíme do různých kontextů, budeme mít desítky nebo dokonce stovky mikroslužeb. Procesy, které dosud existovaly v rámci jediné hranice monolitu, jsou nyní rozprostřeny do více distribuovaných systémů. Dosáhnout transakční integrity a konzistence napříč všemi těmito distribuovanými systémy je velmi obtížné a má to svou cenu – dostupnost systémů.

Mikroslužby jsou také distribuované systémy. Proto se na ně také vztahuje věta CAP – „distribuovaný systém může poskytovat pouze dvě ze tří požadovaných vlastností: konzistenci, dostupnost a toleranci rozdělení („C“, „A“ a „P“ ve slově CAP)“. V reálných systémech se o toleranci rozdělení nedá vyjednávat – síť je nespolehlivá, virtuální stroje mohou vypadnout, latence mezi regiony se může zhoršit atd.

Zůstává nám tedy na výběr buď dostupnost, nebo konzistence. Nyní víme, že v žádné moderní aplikaci není dobré obětovat ani dostupnost.

Obrázek 7: Dostupnost a konzistence. Věta CAP

Navrhujte aplikace kolem případné konzistence

Pokusíte-li se vytvořit transakce v několika distribuovaných systémech, skončíte opět v zemi monolitů. Jenže tentokrát to bude ten nejhorší druh, distribuovaný monolit. Pokud se některý ze systémů stane nedostupným, stane se nedostupným celý proces, což často vede k frustrujícím zkušenostem zákazníků, nesplněným slibům atd. Kromě toho změny jedné služby mohou obvykle znamenat změny jiné služby, což vede ke složitému a nákladnému nasazení. Proto je lepší navrhovat aplikace přizpůsobené našim případům použití tak, aby tolerovaly trochu nekonzistence ve prospěch dostupnosti. V případě výše uvedeného příkladu můžeme všechny procesy udělat asynchronní, a tedy nakonec konzistentní. Můžeme odesílat e-maily asynchronně, nezávisle na ostatních procesech; Pokud slíbená položka není později ve skladu k dispozici, může být položka zpětně objednána nebo můžeme přestat přijímat objednávky na položku přesahující určitou hranici.
Občas se můžete setkat se scénářem, který může vyžadovat silné transakce ve stylu ACID napříč dvěma agregáty v různých hranicích procesů. To je výborné znamení, abychom se k těmto agregátům vrátili a možná je spojili do jednoho. Event Storming a kontextové mapy pomohou identifikovat tyto závislosti včas, než začneme tyto agregáty rozdělovat v různých hranicích procesů. Sloučení dvou mikroslužeb do jedné je nákladné a tomu bychom se měli snažit vyhnout.

Zvýhodněte architekturu řízenou událostmi

Mikroslužby mohou vysílat zásadní změny, které se dějí v jejich agregátech. Těmto událostem se říká události domény a všechny služby, které se o tyto změny zajímají, mohou těmto událostem naslouchat a provádět příslušné akce v rámci svých domén. Tato metoda zabraňuje jakémukoli behaviorálnímu propojení – jedna doména nepředepisuje, co mají dělat ostatní domény, a časovému propojení – úspěšné dokončení procesu nezávisí na tom, aby byly všechny systémy dostupné ve stejnou dobu. To samozřejmě znamená, že systémy budou nakonec konzistentní.

Obr. 8. V případě, že se systémy nacházejí v jedné doméně, je možné, že jsou konzistentní. Architektura řízená událostmi

V uvedeném příkladu služba Orders zveřejňuje událost – Order Cancelled. Ostatní služby, které se přihlásily k události, zpracovávají své příslušné doménové funkce: Služba Payment vrací peníze, služba Inventory upravuje stav zásob zboží atd. Několik věcí, které je třeba si uvědomit, aby byla zajištěna spolehlivost a odolnost této integrace:

  1. Producenti by měli zajistit, aby alespoň jednou vytvořili událost. Pokud při tom selžou, měli by zajistit, aby byl přítomen záložní mechanismus pro opětovné spuštění událostí
  2. Spotřebitelé by měli zajistit, aby spotřebovávali události idempotentním způsobem. Pokud dojde k opakování stejné události, nemělo by dojít k žádnému vedlejšímu účinku na straně spotřebitele. Události mohou také přicházet mimo pořadí. Spotřebitelé mohou použít pole časových značek nebo čísel verzí, aby zaručili jedinečnost událostí.

Vzhledem k povaze některých případů použití nemusí být vždy možné použít integraci založenou na událostech. Podívejte se prosím na integraci mezi službou Košík a službou Platba. Jedná se o synchronní integraci, a tudíž obsahuje několik věcí, na které bychom si měli dát pozor. Je to příklad behaviorální vazby – služba Cart možná volá rozhraní REST API od služby Payment a dává jí pokyn k autorizaci platby za objednávku, a časové vazby – služba Payment musí být k dispozici, aby služba Cart mohla přijmout objednávku. Tento druh vazby snižuje autonomii těchto kontextů a možná vytváří nežádoucí závislost. Existuje několik způsobů, jak se tomuto spřažení vyhnout, ale u všech těchto možností ztratíme možnost poskytovat okamžitou zpětnou vazbu zákazníkům.

  1. Převést rozhraní REST API na integraci založenou na událostech. Tato možnost však nemusí být k dispozici, pokud služba Payment Service vystavuje pouze rozhraní REST API
  2. Služba Cart přijímá objednávku okamžitě a existuje dávková úloha, která vyzvedává objednávky a volá rozhraní API služby Payment Service
  3. Služba Cart vytváří místní událost, která pak volá rozhraní API služby Payment Service

Kombinace výše uvedeného s opakovanými pokusy v případě selhání a nedostupnosti předcházející závislosti – služby Payment Service – může vést k mnohem odolnějšímu návrhu. Například synchronní integraci mezi službami Košík a Platba lze v případě selhání podpořit událostí nebo dávkovým opakováním. Tento přístup má další dopad na zákaznickou zkušenost – zákazníci mohou zadat nesprávné platební údaje a my je nebudeme mít online, když budeme zpracovávat platby offline. Nebo mohou vzniknout dodatečné náklady pro firmu na obnovení neúspěšných plateb. Se vší pravděpodobností však výhody služby Košík, která je odolná vůči nedostupnosti nebo chybám platební služby, převáží nad nedostatky. Můžeme například upozornit zákazníky, pokud nejsme schopni vybrat platby offline. Stručně řečeno, existují kompromisy mezi uživatelským komfortem, odolností a provozními náklady a je moudré navrhovat systémy s ohledem na tyto kompromisy.

Vyhněte se orchestraci mezi službami pro potřeby dat specifických pro spotřebitele

Jedním z anti-vzorů v každé architektuře orientované na služby je, že služby uspokojují specifické přístupové vzory spotřebitelů. Obvykle k tomu dochází, když týmy spotřebitelů úzce spolupracují s týmy služeb. Pokud by tým pracoval na monolitické aplikaci, často by vytvořil jediné rozhraní API, které by překračovalo hranice různých agregátů, a tudíž by tyto agregáty těsně propojil. Uvažujme příklad. Řekněme, že stránka s podrobnostmi o objednávce ve webové a mobilní aplikaci potřebuje na jedné stránce zobrazit podrobnosti o objednávce i podrobnosti o refundacích zpracovaných pro danou objednávku. V monolitické aplikaci se rozhraní API GET pro objednávky – za předpokladu, že se jedná o rozhraní REST API – dotazuje na objednávky a náhrady společně, konsoliduje oba agregáty a volajícím odešle složenou odpověď. To je možné provést bez velké režie, protože agregáty patří do stejné hranice procesu. Spotřebitelé tak mohou získat všechna potřebná data v jediném volání.

Pokud jsou Objednávky a Refundace součástí různých kontextů, data se již nenacházejí v rámci jedné mikroslužby nebo hranice agregátu. Jednou z možností, jak zachovat stejnou funkčnost pro spotřebitele, je učinit službu Objednávky odpovědnou za volání služby Refundace a vytvořit složenou odpověď. Tento přístup způsobuje několik problémů:

1. Služba Objednávka se nyní integruje s jinou službou čistě pro podporu spotřebitelů, kteří potřebují údaje o Refundacích spolu s údaji o Objednávce. Služba Order je nyní méně autonomní, protože jakákoli změna v agregátu Refunds povede ke změně agregátu Order.

2. Služba Order má další integraci, a tudíž další bod selhání, který je třeba vzít v úvahu – pokud služba Refunds vypadne, může služba Order stále odesílat částečná data a mohou spotřebitelé selhat elegantně?

3. Pokud spotřebitelé potřebují změnu, aby získali více dat z agregátu Refunds, jsou nyní zapojeny dva týmy, aby tuto změnu provedly

4. Služba Order je nyní méně autonomní než služba Refunds. Tento vzorec, pokud bude následován v rámci celé platformy, může vést ke složité síti závislostí mezi různými službami domény, a to vše proto, že tyto služby uspokojují specifické přístupové vzory volajících.

Backend for Frontends (BFFs)

Přístupem ke zmírnění tohoto rizika je nechat týmy spotřebitelů spravovat orchestraci mezi různými službami domény. Koneckonců volající znají lépe přístupové vzory a mohou mít plnou kontrolu nad jakýmikoliv změnami těchto vzorů. Tento přístup odděluje doménové služby od prezentační vrstvy a umožňuje jim soustředit se na hlavní obchodní procesy. Pokud však webové a mobilní aplikace začnou volat různé služby přímo namísto jednoho složeného rozhraní API z monolitu, může to těmto aplikacím způsobit výkonnostní režii – vícenásobná volání přes sítě s menší šířkou pásma, zpracování a slučování dat z různých rozhraní API atd.

Místo toho lze použít jiný vzor nazvaný Backend for Front-ends. V tomto návrhovém vzoru se služba backendu vytvořená a spravovaná spotřebiteli – v tomto případě webovými a mobilními týmy – stará o integraci napříč různými doménovými službami čistě za účelem vykreslení zážitku z front-endu pro zákazníky. Webové a mobilní týmy nyní mohou navrhovat datové smlouvy na základě případů použití, které zajišťují. Mohou dokonce používat GraphQL místo rozhraní REST API, aby se pružně dotazovaly a získaly zpět přesně to, co potřebují. Je důležité si uvědomit, že tuto službu vlastní a spravují týmy spotřebitelů, nikoli týmy, které vlastní doménové služby. Front-endové týmy nyní mohou optimalizovat na základě svých potřeb – mobilní aplikace může požadovat menší payload, snížit počet volání z mobilní aplikace atd. Níže se podívejte na revidovaný pohled na orchestraci. Služba BFF nyní pro svůj případ použití volá služby domény Objednávky i Vrácení peněz.

Obr. 9. Backend pro frontendy

Je také užitečné vytvořit službu BFF na počátku, před rozbitím množství služeb z monolitu. Jinak budou muset buď doménové služby podporovat orchestraci mezi doménami, nebo budou muset webové a mobilní aplikace volat více služeb přímo z front-endu. Obě tyto možnosti povedou k výkonnostní režii, zahozené práci a nedostatku autonomie mezi týmy.

Závěr

V tomto blogu jsme se dotkli různých konceptů, strategií a návrhových heuristik, které je třeba zvážit, když se pouštíme do světa mikroslužeb, konkrétně když se snažíme rozdělit monolit na více doménových mikroslužeb. Mnohé z nich jsou samy o sobě rozsáhlými tématy a nemyslím si, že jsme udělali dost pro to, abychom je vysvětlili zcela podrobně, ale chtěli jsme představit některá kritická témata a naše zkušenosti s jejich osvojováním. V sekci Další literatura (odkaz) najdete odkazy a užitečný obsah pro všechny, kteří se chtějí touto cestou vydat.

Aktualizace: Další dva blogy z této série jsou venku. Tyto dva blogy pojednávají o implementaci mikroslužby Cart s příklady kódu s využitím principů Domain-Driven Design a návrhových vzorů Ports a Adapters. Hlavním cílem těchto blogů je ukázat, jak nám tyto dva principy/vzory pomáhají vytvářet modulární aplikace, které jsou agilní, testovatelné a refaktorovatelné – zkrátka jsou schopné reagovat na rychle se měnící prostředí, ve kterém se všichni pohybujeme.

Implementace mikroslužby Cart pomocí Domain Driven Design a Ports and Adapters Pattern – část 1

Implementace mikroslužby Cart pomocí Domain Driven Design a Ports and Adapters Pattern – část 2

Další čtení

1. Eric Evans Domain Driven Design

2. Vaughn Vernon Implementing Domain Driven Design

3. Martin Fowler článek o mikroslužbách

4. Sam Newman Building Microservices

5. Event storming

7. Backend pro frontendy

8. Omyly distribuovaných výpočtů

.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna.