História architektúry Dodo IS: raný monolit

Alebo každá nešťastná firma s monolitom je nešťastná svojim spôsobom.

Vývoj systému Dodo IS začal okamžite, podobne ako podnikanie Dodo Pizza - v roku 2011. Bol založený na myšlienke úplnej a totálnej digitalizácie podnikových procesov a samy osebe, čo už vtedy v roku 2011 vyvolalo mnohé otázniky a skepsu. Ale už 9 rokov ideme touto cestou – vlastným vývojom, ktorý začal monolitom.

Tento článok je „odpoveďou“ na otázky „Prečo prepisovať architektúru a robiť také rozsiahle a dlhodobé zmeny? k predchádzajúcemu článku „História architektúry Dodo IS: cesta back office“. Začnem tým, ako sa začal vývoj Dodo IS, ako vyzerala pôvodná architektúra, ako sa objavili nové moduly a kvôli akým problémom bolo potrebné vykonať rozsiahle zmeny.

História architektúry Dodo IS: raný monolit

Séria článkov "Čo je Dodo IS?" hovorí o:

  1. Raný monolit v Dodo IS (2011-2015). (ste tu)

  2. Cesta Back Office: Oddelené základne a autobus.

  3. Cesta na strane klienta: fasáda nad základňou (2016-2017). (Prebieha...)

  4. História skutočných mikroslužieb. (2018-2019). (Prebieha...)

  5. Hotové pílenie monolitu a stabilizácia architektúry. (Prebieha...)

Prvotná architektúra

V roku 2011 vyzerala architektúra Dodo IS takto:

História architektúry Dodo IS: raný monolit

Prvým modulom v architektúre je prijímanie objednávok. Obchodný proces bol takýto:

  • zákazník zavolá do pizzérie;

  • Manažér zdvihne telefón;

  • prijíma objednávky cez telefón;

  • Zároveň ho vyplní v rozhraní prijímania objednávky: do úvahy sa berú údaje o klientovi, údaje o detailoch objednávky, adresa doručenia. 

Rozhranie informačného systému vyzeralo asi takto...

Prvá verzia z októbra 2011:

Mierne zlepšenie v januári 2012

Informačný systém Dodo Rozvoz pizze Pizza Restaurant

Zdroje na vývoj prvého modulu prijímania objednávok boli obmedzené. Bolo potrebné urobiť veľa, rýchlo a s malým tímom. Malý tím tvoria 2 vývojári, ktorí položili základy celého budúceho systému.

Ich prvé rozhodnutie určilo budúci osud technologického zásobníka:

  • Backend na ASP.NET MVC, jazyk C#. Vývojári boli dotnetteri, tento zásobník im bol známy a príjemný.

  • Frontend na Bootstrap a JQuery: používateľské rozhrania založené na vlastných štýloch a skriptoch. 

  • Databáza MySQL: žiadne licenčné náklady, jednoduché použitie.

  • Servery na Windows Server, pretože .NET by potom mohol byť iba na Windows (nebudeme diskutovať o Mono).

Fyzicky to bolo všetko vyjadrené na „stole hostiteľa“. 

Architektúra aplikácie na prijatie objednávky

V tom čase už všetci hovorili o mikroslužbách a SOA sa vo veľkých projektoch používala asi 5 rokov, napríklad WCF vyšlo v roku 2006. Potom však zvolili spoľahlivé a osvedčené riešenie.

Tu to je.

História architektúry Dodo IS: raný monolit

Asp.Net MVC je Razor, ktorý na požiadanie z formulára alebo od klienta vytvorí HTML stránku s vykreslením na serveri. Na klientovi už CSS a JS skripty zobrazujú informácie a v prípade potreby vykonávajú AJAX požiadavky cez JQuery.

Požiadavky na serveri spadajú do tried *Controller, kde metóda spracováva a generuje finálnu HTML stránku. Kontroléry odosielajú požiadavky na vrstvu logiky nazývanú *Služby. Každá zo služieb zodpovedala nejakému aspektu podnikania:

  • Napríklad DepartmentStructureService poskytoval informácie o pizzeriách a oddeleniach. Oddelenie je skupina pizzerií ​​riadená jedným franšízantom.

  • ReceivingOrdersService prijala a vypočítala obsah objednávky.

  • A SmsService poslal SMS volaním služieb API na odosielanie SMS.

Služby spracovávali údaje z databázy a ukladali obchodnú logiku. Každá služba mala jedno alebo viacero *úložísk s príslušným názvom. Obsahovali už dotazy na uložené procedúry v databáze a vrstvu mapovačov. Repozitáre mali obchodnú logiku, najmä veľa z nich, ktoré produkovali údaje zo správ. ORM sa nepoužívalo, všetci sa spoliehali na ručne písané sql. 

K dispozícii bola aj vrstva doménového modelu a všeobecné pomocné triedy, napríklad trieda Order, ktorá uložila objednávku. Tam sa vo vrstve nachádzal pomocník na prevod zobrazovaného textu podľa zvolenej meny.

To všetko môže reprezentovať tento model:

História architektúry Dodo IS: raný monolit

Spôsob objednávky

Uvažujme o zjednodušenom počiatočnom spôsobe vytvorenia takejto objednávky.

História architektúry Dodo IS: raný monolit

Pôvodne bola stránka statická. Boli na nej ceny a navrchu bolo telefónne číslo a nápis „Ak chceš pizzu, zavolaj na číslo a objednaj“. Na objednávku musíme implementovať jednoduchý postup: 

  • Klient prejde na statický web s cenami, vyberie si produkty a zavolá na číslo uvedené na webe.

  • Zákazník pomenuje produkty, ktoré chce pridať do objednávky.

  • Uvádza svoju adresu a meno.

  • Prevádzkovateľ objednávku akceptuje.

  • Objednávka sa zobrazí v rozhraní prijatých objednávok.

Všetko to začína zobrazením ponuky. Prihlásený používateľ operátora akceptuje vždy iba jednu objednávku. Preto môže byť koncept košíka uložený v jeho relácii (relácia používateľa je uložená v pamäti). Existuje objekt košíka obsahujúci produkty a informácie o zákazníkoch.

Klient pomenuje produkt, operátor klikne + vedľa produktu a na server sa odošle požiadavka. Informácie o produkte sa vytiahnu z databázy a informácie o produkte sa vložia do košíka.

História architektúry Dodo IS: raný monolit

Poznámka. Áno, tu nemusíte vyťahovať produkt z databázy, ale preniesť ho z frontendu. Ale pre názornosť som presne ukázal cestu od základne. 

Ďalej zadajte adresu a meno klienta. 

História architektúry Dodo IS: raný monolit

Keď kliknete na „Vytvoriť objednávku“:

  • Žiadosť odošleme do OrderController.SaveOrder().

  • Dostávame košík z relácie, sú tam produkty v množstve, ktoré potrebujeme.

  • Do košíka doplníme informácie o klientovi a odovzdáme ho metóde AddOrder triedy ReceivingOrderService, kde sa uloží do databázy. 

  • V databáze sú tabuľky s objednávkou, obsahom objednávky, klientom a všetky sú prepojené.

  • Rozhranie zobrazenia objednávok prejde a vytiahne najnovšie objednávky a zobrazí ich.

Nové moduly

Prijatie objednávky bolo dôležité a nevyhnutné. Nemôžete podnikať s pizzou, ak nemáte objednávku na predaj. Preto systém začal získavať funkčnosť - približne od roku 2012 do roku 2015. Počas tejto doby sa objavilo veľa rôznych blokov systému, ktoré budem nazývať modulov, na rozdiel od konceptu služby alebo produktu. 

Modul je súbor funkcií, ktoré spája nejaký spoločný obchodný cieľ. Navyše sú fyzicky umiestnené v rovnakej aplikácii.

Moduly možno nazvať systémové bloky. Ide napríklad o reportovací modul, administrátorské rozhrania, sledovač kuchynských produktov, autorizácia. Všetko sú to rôzne používateľské rozhrania, niektoré majú dokonca rôzne vizuálne štýly. Všetko je navyše v rámci jednej aplikácie, jedného spusteného procesu. 

Technicky boli moduly navrhnuté ako Area (táto myšlienka dokonca zostala v jadro asp.net). Existovali samostatné súbory pre frontend, modely, ako aj ich vlastné triedy radičov. V dôsledku toho bol systém transformovaný z takých...

História architektúry Dodo IS: raný monolit

...do tohto:

História architektúry Dodo IS: raný monolit

Niektoré moduly sú implementované samostatnými stránkami (spustiteľný projekt), kvôli úplne oddelenej funkcionalite a čiastočne kvôli trochu oddelenému, viac zameranému vývoju. toto:

  • Miesto - prvá verzia webová stránka dodopizza.ru.

  • export: sťahovanie správ z Dodo IS pre 1C. 

  • Osobné — osobný účet zamestnanca. Bol vyvinutý samostatne a má svoj vlastný vstupný bod a samostatný dizajn.

  • fs — projekt pre statický hosting. Neskôr sme sa od neho vzdialili a presunuli sme všetok statický obsah do Akamai CDN. 

Zvyšné bloky sa nachádzali v aplikácii BackOffice. 

História architektúry Dodo IS: raný monolit

Vysvetlenie mien:

  • Pokladňa - Reštauračná pokladňa.

  • ShiftManager - rozhrania pre rolu „Shift Manager“: prevádzkové štatistiky o predaji pizzerie, možnosť zaradiť produkty na stoplist, zmeniť objednávku.

  • OfficeManager – rozhrania pre roly „Správca pizzerie“ a „Nadobúdateľ franšízy“. Nájdete tu funkcie pre zriadenie pizzerie, jej bonusové akcie, príjem a prácu so zamestnancami a reporty.

  • PublicScreens - rozhrania pre televízory a tablety zavesené v pizzeriách. Televízory pri doručení zobrazujú menu, reklamné informácie a stav objednávky. 

Používali spoločnú vrstvu služieb, spoločný blok doménových tried Dodo.Core a spoločnú základňu. Niekedy ešte mohli viesť cez priechody k sebe. Okrem toho jednotlivé stránky, ako napríklad dodopizza.ru alebo personal.dodopizza.ru, tiež pristupovali k bežným službám.

Keď sa objavili nové moduly, snažili sme sa čo najviac opätovne využiť už vytvorený kód pre služby, uložené procedúry a tabuľky v databáze. 

Pre lepšie pochopenie rozsahu modulov vytvorených v systéme je tu diagram z roku 2012 s plánmi rozvoja:

História architektúry Dodo IS: raný monolit

Do roku 2015 bolo všetko na dobrej ceste a ešte viac sa vyrábalo.

  • Prijímanie objednávok sa rozrástlo na samostatný blok Kontaktného centra, kde objednávku prijíma operátor.

  • V pizzeriách sa objavili verejné obrazovky s menu a informáciami.

  • Kuchyňa má modul, ktorý automaticky prehrá hlasovú správu „Nová pizza“ pri príchode novej objednávky a vytlačí aj faktúru pre kuriéra. To výrazne zjednodušuje procesy v kuchyni a umožňuje zamestnancom, aby neboli rozptyľovaní veľkým množstvom jednoduchých operácií.

  • Z doručovacieho bloku sa stala samostatná Doručovacia pokladňa, kde bola objednávka vystavená kuriérovi, ktorý si predtým zobral smenu. Pri výpočte mzdy sa zohľadnil jeho pracovný čas. 

Paralelne od roku 2012 do roku 2015 sa objavilo viac ako 10 vývojárov, otvorilo sa 35 pizzerií, systém bol nasadený v Rumunsku a pripravený na otvorenie miest v USA. Vývojári už neboli zapojení do všetkých úloh, ale boli rozdelení do tímov. každý sa špecializuje na svoju časť systému. 

Problémy

Vrátane kvôli architektúre (ale nielen).

Chaos v základni

Jedna základňa je pohodlná. Je možné dosiahnuť konzistentnosť a to na úkor nástrojov zabudovaných do relačných databáz. Práca s ním je známa a pohodlná, najmä ak je málo tabuliek a málo údajov.

Ale za 4 roky vývoja databáza obsahovala asi 600 tabuliek, 1500 uložených procedúr, z ktorých mnohé mali aj logiku. Bohužiaľ, uložené procedúry neposkytujú pri práci s MySQL veľa výhod. Databáza ich neukladá do vyrovnávacej pamäte a ukladanie logiky v nich komplikuje vývoj a ladenie. Opätovné použitie kódu je tiež ťažké.

Mnohé tabuľky nemali vhodné indexy, niekde, naopak, bolo veľa indexov, čo sťažovalo vkladanie. Muselo sa upraviť asi 20 tabuliek – transakcia na vytvorenie objednávky mohla trvať asi 3-5 sekúnd. 

Údaje v tabuľkách neboli vždy v najvhodnejšej forme. Niekde bolo treba urobiť denormalizáciu. Časť pravidelne prijímaných údajov bola v stĺpci vo forme XML štruktúry, čo predlžovalo čas vykonávania, predlžovalo dopytovanie a komplikovalo vývoj.

Rovnaké tabuľky podliehali veľmi heterogénne požiadavky. Populárne stoly, ako napríklad vyššie uvedená tabuľka, boli obzvlášť ovplyvnené objednávky alebo tabuľky pizzerie. Boli použité na zobrazenie prevádzkových rozhraní v kuchyni a analytiky. Stránka ich tiež kontaktovala (dodopizza.ru), kde môže naraz prísť veľa žiadostí v ľubovoľnom čase. 

Údaje neboli agregované a mnoho výpočtov prebiehalo za behu pomocou základne. Vznikli tak zbytočné výpočty a dodatočné zaťaženie. 

Kód sa často dostal do databázy, keď to nemohol urobiť. Niekde chýbali hromadné operácie, niekde by bolo potrebné pre zrýchlenie a zvýšenie spoľahlivosti jednu požiadavku rozdeliť cez kód na viacero. 

Súdržnosť a zmätok v kódexe

Moduly, ktoré mali byť zodpovedné za svoju časť biznisu, to nerobili poctivo. Niektoré z nich mali duplicitné funkcie pre roly. Napríklad miestny obchodník, ktorý je zodpovedný za marketingovú aktivitu siete vo svojom meste, musel použiť rozhranie „Admin“ (na nastavenie akcií) aj rozhranie „Office Manager“ (na zobrazenie vplyvu akcií na podnikanie). Samozrejme vo vnútri oboch modulov bola použitá rovnaká služba, ktorá fungovala s bonusovými akciami.

Služby (triedy v rámci jedného monolitického veľkého projektu) by si mohli navzájom volať, aby obohatili svoje dáta.

So samotnými modelovými triedami, ktoré uchovávajú údaje, práca v kóde bola vykonaná inak. Niekde boli konštruktory, prostredníctvom ktorých ste mohli špecifikovať požadované polia. Niekde sa to dialo prostredníctvom verejných nehnuteľností. Samozrejme, získavanie a transformácia údajov z databázy bola rôznorodá. 

Logika bola buď v radičoch alebo servisných triedach. 

Zdá sa, že ide o menšie problémy, ale značne spomalili vývoj a znížili kvalitu, čo viedlo k nestabilite a chybám. 

Zložitosť veľkého rozvoja

Ťažkosti nastali pri samotnom vývoji. Bolo potrebné vytvoriť rôzne bloky systému a paralelne. Bolo čoraz ťažšie vtesnať potreby každého komponentu do jedného kódu. Nebolo jednoduché dohodnúť sa a zároveň potešiť všetky zložky. K tomu sa pridali obmedzenia v technológii, najmä čo sa týka základne a prednej časti. Bolo potrebné opustiť JQuery v prospech rámcov na vysokej úrovni, najmä z hľadiska klientskych služieb (web).

Niektoré časti systému by mohli využívať databázy, ktoré sú na to vhodnejšie. Napríklad neskôr sme mali precedens prechodu z Redis na CosmosDB na uloženie objednávkového košíka. 

Tímy a vývojári pracujúci v ich oblasti jednoznačne chceli väčšiu nezávislosť svojich služieb, a to z hľadiska vývoja aj z hľadiska zavádzania. Konflikty pri spájaní, problémy pri vydávaní. Ak je tento problém pre 5 vývojárov bezvýznamný, potom s 10 a ešte viac s plánovaným rastom by sa všetko stalo vážnejším. A čo malo prísť, bol vývoj mobilnej aplikácie (začalo sa to v roku 2017 a v roku 2018 veľký pád). 

Rôzne časti systému vyžadovali rôzne ukazovatele stability, ale vzhľadom na silnú konektivitu systému sme to nemohli poskytnúť. Chyba pri vývoji novej funkcie v administračnom paneli mohla mať za následok prijatie objednávky na stránke, pretože kód je bežný a opakovane použiteľný, databáza a údaje sú tiež rovnaké.

V rámci takejto monoliticko-modulárnej architektúry by sa asi dalo týmto chybám a problémom vyhnúť: vytvoriť oddelenie zodpovedností, zrefaktorovať kód aj databázu, jasne oddeliť vrstvy od seba a sledovať kvalitu každý deň. No zvolené architektonické riešenia a orientácia na rýchle rozšírenie funkčnosti systému viedli k problémom v otázkach stability.

Ako blog Power of Mind umiestnil pokladne do reštaurácií

Ak by rast siete pizzerií ​​(a záťaže) pokračoval rovnakým tempom, tak po čase by boli prepady také, že by sa systém nezotavil. Nasledujúci príbeh dobre ilustruje problémy, ktorým sme začali čeliť v roku 2015. 

V blogu"Sila mysle„existoval widget, ktorý zobrazoval údaje o príjmoch za rok pre celú sieť. Widget pristúpil k verejnému API Dodo, ktoré poskytuje tieto údaje. Tieto štatistiky sú teraz k dispozícii na http://dodopizzastory.com/. Miniaplikácia sa zobrazovala na každej stránke a každých 20 sekúnd robila požiadavky na časovač. Žiadosť smerovala na api.dodopizza.ru s otázkou:

  • počet pizzerií ​​v sieti;

  • celkové výnosy zo siete od začiatku roka;

  • dnešný príjem.

Požiadavka na štatistiku tržieb išla priamo do databázy a začala požadovať údaje o objednávkach, priamo za chodu agregovať údaje a vydávať sumu. 

Pokladne v reštauráciách išli do tej istej tabuľky objednávok, nahrali zoznam prijatých objednávok na dnes a pribudli do nej nové objednávky. Pokladne žiadali každých 5 sekúnd alebo pri obnove stránky.

Diagram vyzeral takto:

História architektúry Dodo IS: raný monolit

Jedného dňa na jeseň napísal Fjodor Ovčinnikov na svoj blog dlhý a populárny článok. Na blog prišlo veľa ľudí a začali všetko pozorne čítať. Zatiaľ čo každý z ľudí, ktorí prišli, čítal článok, widget príjmov fungoval správne a každých 20 sekúnd požadoval API.

API volalo uloženú procedúru na výpočet množstva všetkých objednávok od začiatku roka pre všetky pizzérie v sieti. Agregácia bola založená na tabuľke objednávok, ktorá je veľmi populárna. Chodia do nej všetky pokladne všetkých vtedy otvorených reštaurácií. Pokladne prestali reagovať a objednávky neprijímali. Neboli tiež prijaté zo stránky, nezobrazovali sa na sledovači a vedúci zmeny ich nemohol vidieť vo svojom rozhraní. 

Toto nie je jediný príbeh. Na jeseň roku 2015 bolo zaťaženie systému každý piatok kritické. Niekoľkokrát sme vypli verejné API a raz sme dokonca museli vypnúť stránku, pretože nič nepomáhalo. Bol tam dokonca zoznam služieb s poradím odstavenia pri veľkom zaťažení.

Od tejto chvíle začína náš boj so záťažou a o stabilizáciu systému (od jesene 2015 do jesene 2018). Vtedy sa to stalo"Veľký pád" Ďalej sa niekedy vyskytli aj zlyhania, z ktorých niektoré boli veľmi citlivé, ale všeobecné obdobie nestability možno teraz považovať za ukončené.

Rýchly rast podnikania

Prečo by sa to nedalo urobiť „okamžite dobre“? Stačí sa pozrieť na nasledujúce grafy.

História architektúry Dodo IS: raný monolit

Aj v rokoch 2014-2015 bolo otvorenie v Rumunsku a pripravovalo sa otvorenie v USA.

Reťazec sa veľmi rýchlo rozrástol, otvorili sa nové krajiny, objavili sa nové formáty pizzerií, otvorila sa napríklad pizzeria vo food courte. To všetko si vyžadovalo značnú pozornosť konkrétne rozšíreniu funkcií Dodo IS. Bez všetkých týchto funkcií, bez sledovania v kuchyni, účtovania produktov a strát v systéme, zobrazovania doručenia objednávok v hale food courtu, je nepravdepodobné, že by sme teraz hovorili o „správnej“ architektúre a „správnej“. “ prístup k rozvoju.

Ďalšou prekážkou včasnej revízie architektúry a všeobecnej pozornosti technickým problémom bola kríza v roku 2014. Takéto veci poškodzujú možnosti rastu tímov, najmä pre mladý podnik, akým je Dodo Pizza.

Rýchle riešenia, ktoré pomohli

Problémy potrebovali riešenia. Bežne možno riešenia rozdeliť do 2 skupín:

  • Rýchle, ktoré uhasia oheň a poskytnú nám malú rezervu bezpečia a poskytnú nám čas na zmenu.

  • Systémové a teda dlhé. Reengineering niekoľkých modulov, rozdelenie monolitickej architektúry na samostatné služby (väčšina z nich nie sú mikro, ale skôr makro služby a o tom je viac správa Andrey Morevsky). 

Suchý zoznam rýchlych zmien je:

Zväčšiť základnú predlohu

Samozrejme, prvá vec, ktorá sa robí v boji proti záťaži, je zvýšenie výkonu servera. Toto bolo vykonané pre hlavnú databázu a webové servery. Bohužiaľ, je to možné len do určitej hranice, nad ktorou je to príliš drahé.

Od roku 2014 sme prešli do Azure, o tejto téme sme už vtedy písali v článku “Ako Dodo Pizza doručuje pizzu pomocou cloudu Microsoft Azure" Po sérii zvyšovaní servera však náklady na základňu dosiahli limit. 

Repliky databázy na čítanie

Pre základňu sme urobili dve repliky:

ReadReplica pre žiadosti o adresár. Používa sa na čítanie adresárov, ako je mesto, ulica, pizzeria, produkty (pomaly zmenená doména) a v tých rozhraniach, kde je prijateľné malé oneskorenie. Tieto repliky boli 2, ich dostupnosť sme zabezpečili rovnako ako predlohu.

ReadReplica pre žiadosti o zostavu. Táto databáza mala nižšiu dostupnosť, ale všetky hlásenia do nej chodili. Môžu mať veľké požiadavky na veľké prepočty údajov, ale neovplyvňujú hlavnú databázu a operačné rozhrania. 

Vyrovnávacia pamäť v kóde

Nikde v kóde neboli žiadne kešky (vôbec). To viedlo k dodatočným, nie vždy potrebným požiadavkám na načítanú databázu. Najprv boli vyrovnávacie pamäte v pamäti aj na externej vyrovnávacej službe, bola to Redis. Všetko bolo časovo neplatné, nastavenia boli špecifikované v kóde.

Viac serverov pre backend

Backend aplikácie musel byť tiež škálovaný, aby vydržal zvýšené zaťaženie. Z jedného IIS servera bolo potrebné vytvoriť klaster. Presťahovali sme sa relácia aplikácie z pamäte na RedisCache, čo umožnilo vytvoriť niekoľko serverov za jednoduchým vyrovnávačom záťaže s round robin. Najprv sa používal rovnaký Redis ako na kešky, potom sa rozdelili na niekoľko. 

V dôsledku toho sa architektúra stala zložitejšou...

História architektúry Dodo IS: raný monolit

...ale trochu napätia sa uvoľnilo.

A potom bolo potrebné prerobiť načítané komponenty, čo sme si vzali na seba. O tom si povieme v ďalšej časti.

Zdroj: hab.com

Pridať komentár