Vymanit se z Monolith

A jak jsme se vyvinuli s Microservices

(19. července 2018)

Monolith vládnoucí kódové opice

V Coniu to všechno začalo tím, co se běžně nazývá „monolit“. To znamená, že jedna základna kódu obsahuje vše, co je v plné aplikaci: její frontendové komponenty, backendové komponenty, služby API, úlohy na pozadí; sakra, dokonce vyvíjí skripty. A na začátku to fungovalo velmi dobře. Pouze pár softwarových inženýrů pracujících na samostatných oblastech kódové základny (takže velmi malé šance na konflikty při změně kódu) se snadno nasadí. Plné zaměření na psaní aplikačních funkcí, aniž byste se museli starat o mnoho dalšího. Jak jsme přistupovali k nasazení? Vzhledem k tomu, že si stále několik vývojářů beta uvědomuje jen několik beta verzí, nebylo skutečným problémem na chvíli vypnout služby a zavést úplnou základnu kódu (bez ohledu na to, jak malé nebo velké byly celkové změny a zda zahrnovaly migraci databáze), a pak znovu nabídnout služby.

Bylo rozhodně uspokojivé vidět produkt, který se od základu formuje, a získat ocenění od koncových zákazníků. Věděli jsme však velmi dobře, že tento přístup není vhodný pro moderní společnost Fintech.

Co potom?

S většinou softwarových aplikací jsou zákazníci docela tolerantní. Ano, Whatsapp může přestat fungovat a mít výpadek trvající několik hodin: rozhodně obtěžování, ale ne vnímaný problém. Totéž platí pro Pokemon Go nebo vaši oblíbenou herní aplikaci. To však neplatí, pokud jde o peníze : nálada se změní, pokud se nemůžete přihlásit ke svému bankovnímu účtu nebo nejste schopni provádět obchodní operace. To je v případě kryptoměnových aplikací ještě horší: většina lidí si pamatuje nechvalně známé omyly minulosti a kdykoli nejsou schopni na krátkou dobu získat přístup ke svým fondům kryptoměny, objeví se spekulace. To je fér. Jsou to vaše peníze a pokud byste je chtěli použít, měli byste mít malý nebo žádný problém.

Výše ​​uvedený Monolith se na takový scénář nehodí: jakákoli změna základny kódu ve výrobě by vyžadovala úplné nasazení, s přidruženými odstávkami. Každý den pracujeme na zlepšování našich služeb tím, že opravujeme chyby, děláme naše rozhraní ještě přátelštějším, odstraňujeme staré funkce a přidáváme nové, které mají lepší využití. Tyto aktualizace vydáváme často každý den, aby naši zákazníci mohli mít okamžitý užitek, a snažíme se, aby to nemělo žádný dopad na zkušenosti zákazníka. To znamená, že jakýkoli vzorec, který vymyslíme v zákulisí, musí být pro vnější svět neviditelný (alespoň většinou). Takže jsme se vzdálili od Monolithu a vybrali jsme si to, co se běžně nazývá „architektura mikroslužeb“.

Vývoj prostřednictvím Microservices

Masivní pevně slepená jednoduchá základna kódu je nyní rozložena na menší části, z nichž každá představuje konkrétní službu. Kdykoli jsou služby spuštěny, vzájemně komunikují synchronně pomocí standardního protokolu HTTP a asynchronně prostřednictvím front (zpracovává je například RabbitMQ a Apache Kafka).

Interakce v architektuře Microservices

Začátek rozpadu monolitu na menší součásti je docela náročné, ale stojí to za to úsilí. Z vojenského hlediska je to velmi podobné tomu, co udělal Julius Caesar, aby stabilně vládl velkému území Gallie: „ rozděl a panuj “.

1) Produkt lze nasadit nepřetržitě. Aktualizace kódu nyní platí pouze pro mikroslužbu: ve většině případů ji lze okamžitě nasadit do produkce a vydat bez dopadu na zákazníka.

2) Správa kódu je snazší. Z pohledu organizace společnosti se věci změní, když se tým 2 softwarových inženýrů stane týmem 10 softwarových inženýrů. Když je každý člen týmu zodpovědný za svou vlastní mikroslužbu, je to efektivnější a s méně konflikty kódu.

3) Udržování kódu je snazší. Architektura Microservices vyžaduje ze své podstaty definici rozhraní pro komunikaci s vnějším světem (ať už jde o front-endovou aplikaci nebo jinou back-endovou službu) a je zcela izolována od jakéhokoli jiného hlediska. To umožňuje zkontrolovat, přepracovat nebo dokonce úplně přepsat od začátku (i v různých jazycích, pokud je to vhodné) jednotlivé komponenty aplikace, aniž by to mělo dopad na ostatní.

4) Výkon lze zvýšit. Každá mikroslužba nyní může používat svůj nejvhodnější jazyk. Těžké kryptografické výpočetní komponenty lze například optimalizovat v jazyce C, zatímco služby API v Pythonu a dlouhotrvající úlohy v Go.

5) Vylepšená izolace a zabezpečení kódu. Každá mikroslužba může být spuštěna ve vlastním kontejneru Docker, což poskytuje izolaci privilegií, segregaci sítí a dat a má zásadní význam pro fázi růstu, obrovský potenciál škálovatelnosti.

Jsou tedy Microservices odpovědí?

Samozřejmě neexistuje nic jako oběd zdarma. Architektura Microservices přichází také s vlastní sadou náročných výzev:

1) Provozní složitost. Inženýři DevOps jsou rozhodně potřební k uhlazení složitosti nového procesu nasazení.

2) Hardwarové nafouknutí. Mikroslužby se často spouštějí v kontejnerech Dockeru; jakmile se počet mikroslužeb rozmnoží, je stále náročnější spouštět plnou aplikaci na stejném hardwaru jako dříve.

3) Režijní náklady na komunikaci: každý požadavek může vyžadovat interakci s jednou nebo více různými mikroslužby prostřednictvím sítě. To může způsobit zvýšenou latenci a může podléhat dočasným poruchám. Aby bylo možné implementovat odolné služby a zlepšit škálovatelnost celého systému, je nutné přesunout interakce na asynchronní zasílání zpráv (např. Pomocí Apache Kafka nebo RabbitMQ)

4) Případná konzistence. Toto je pravděpodobně nejtěžší výzva architektury Microservices. Vzhledem k jediné mikroslužbě je možné v rámci jejích hranic vytvářet transakce RDBMS. . Běžným problémem v distribuovaných architekturách je bohužel řešení několika transakcí, které nejsou ve stejných hranicích. Ve výsledku může systém skončit v nelegálním a neobnovitelném stavu. Aby se tyto problémy zmírnily, Conio přijímá různé strategie:

  1. Následující postupy Domain Driven Design rozkládají domény vyšší úrovně na subdomény a omezují je na jednotlivě ohraničené kontexty ; každý ohraničený kontext je implementován jako mikroslužba, kde jsou použity hranice transakcí. Tím se vyřeší možnost mít nesrovnalosti pro konkrétní subdomény.
  2. Implementujte idempotentní asynchronní interakce, které dříve nebo později nesrovnalosti vyřeší.
  3. Kdykoli je to možné, vyhněte se jakékoli akci, která by mohla zahrnovat více subdomén.

5) Složité přehledy. Vzhledem k tomu, že každá subdoména žije v konkrétním ohraničeném kontextu, může složité sestavy, které zahrnují více subdomén, vyžadovat dotazování na data z více zdrojů dat: to může mít negativní dopad jak na expresivitu domén, tak na škálovatelnost systému. Tady v Conio jsme přijali architekturu CQRS na podporu zpráv o činnosti backoffice a obchodních analýz.

6 ) Systém protokolování. Každý prvek v distribuovaném systému přispívá k vytvoření protokolu celého systému. Je však nutné implementovat nástroje, které mohou vytvořit potřebná spojení mezi všemi takovými oddělenými protokoly, aby byl pro každou interakci jednotný protokol. Tady v Coniu používáme zásobník ELK (ElasticSearch, Logstash, Kibana) k ukládání a dotazování na data protokolu: každý protokol je obohacen o potřebná korelační ID, která umožňují výše uvedený jednotný protokol.

Nikdy nezastavujte vývoj

Náš názor? Rozklad počátečního jediného základu kódu je třeba považovat za dlouhodobý úkol s neustále se opakujícími vylepšeními. Ve společnosti Conio nám to trvalo pár let, kdy jsme se krok za krokem přesunuli z 1 masivní kódové základny na více než 100 mikroslužeb. Přišli jsme do bodu, kdy jsme na výsledky hrdí, ale zároveň stále zkoumáme. Existuje několik možných nových optimalizací: přechod z Docker Swarm do Kubernetes? Migrujete služby typu backend-for-frontend na funkce lambda bez serveru? Přepínáte na tok provozu nepřetržitého plného nasazení? Možnosti jsou nekonečné.

Dotkli jsme se zde řady témat a technologií. V následujících článcích budeme sdílet další podrobnosti o našich zjištěních a pokroku. Pokud chcete, můžete nám sdělit své zkušenosti a zkušenosti.

Napsat komentář

Vaše e-mailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *