Zgodovina arhitekture Dodo IS: zgodnji monolit

Ali pa je vsako nesrečno podjetje z monolitom nesrečno na svoj način.

Razvoj sistema Dodo IS se je začel takoj, tako kot posel Dodo Pizza leta 2011. Temeljil je na ideji popolne in celovite digitalizacije poslovnih procesov ter sami, ki je že takrat leta 2011 sprožil veliko vprašanj in skepse. A že 9 let gremo po tej poti - z lastnim razvojem, ki se je začel z monolitom.

Ta članek je "odgovor" na vprašanja "Zakaj prepisati arhitekturo in narediti tako obsežne in dolgoročne spremembe?" nazaj na prejšnji članek "Zgodovina arhitekture Dodo IS: pot zaledne pisarne". Začel bom s tem, kako se je začel razvoj Dodo IS, kako je izgledala prvotna arhitektura, kako so se pojavili novi moduli in zaradi kakšnih težav so bile potrebne obsežne spremembe.

Zgodovina arhitekture Dodo IS: zgodnji monolit

Serija člankov "Kaj je Dodo IS?" pripoveduje o:

  1. Zgodnji monolit v Dodo IS (2011-2015). (tukaj ste)

  2. Pot zaledne pisarne: ločene baze in avtobus.

  3. Pot s strani naročnika: fasada nad podstavkom (2016-2017). (V delu...)

  4. Zgodovina pravih mikrostoritev. (2018-2019). (V delu...)

  5. Končano žaganje monolita in stabilizacija arhitekture. (V delu...)

Začetna arhitektura

Leta 2011 je bila arhitektura Dodo IS videti takole:

Zgodovina arhitekture Dodo IS: zgodnji monolit

Prvi modul v arhitekturi je sprejem naročila. Poslovni proces je bil:

  • naročnik pokliče picerijo;

  • vodja dvigne telefon;

  • sprejema naročilo po telefonu;

  • vzporedno izpolni v vmesniku za sprejemanje naročil: upoštevajo se podatki o naročniku, podatki o podrobnostih naročila, naslov za dostavo. 

Vmesnik informacijskega sistema je izgledal nekako takole ...

Prva različica iz oktobra 2011:

Rahlo izboljšano januarja 2012

Informacijski sistem Dodo Pizza Dostava Pizza Restaurant

Viri za razvoj prvega modula sprejemanja naročil so bili omejeni. Morali smo narediti veliko, hitro in z majhno ekipo. Majhna ekipa je 2 razvijalca, ki sta postavila temelje za celoten bodoči sistem.

Njihova prva odločitev je določila usodo tehnološkega sklada:

  • Zaledje na ASP.NET MVC, jezik C#. Razvijalci so bili dotnetchiki, ta sklad jim je bil znan in prijeten.

  • Frontend na Bootstrap in JQuery: uporabniški vmesniki na samonapisanih slogih in skriptih. 

  • Baza podatkov MySQL: brez stroškov licence, enostavna uporaba.

  • Strežniki na Windows Server, ker bi .NET takrat lahko bil samo pod Windows (o Mono ne bomo razpravljali).

Fizično se je vse to izražalo v “dedicu pri hosterju”. 

Arhitektura aplikacije Order Intake

Potem so vsi že govorili o mikrostoritvah, SOA pa je bila v velikih projektih uporabljena 5 let, na primer WCF je bil izdan leta 2006. Potem pa so izbrali zanesljivo in preverjeno rešitev.

Tukaj je.

Zgodovina arhitekture Dodo IS: zgodnji monolit

Asp.Net MVC je Razor, ki na zahtevo obrazca ali odjemalca upodobi stran HTML s strežniškim upodabljanjem. Na odjemalcu skripti CSS in JS že prikazujejo informacije in po potrebi izvajajo zahteve AJAX prek JQuery.

Zahteve na strežniku končajo v razredih *Controller, kjer v metodi poteka obdelava in generiranje končne strani HTML. Krmilniki postavljajo zahteve ravni logike, imenovani *Storitve. Vsaka od storitev je ustrezala določenemu vidiku poslovanja:

  • Na primer, DepartmentStructureService je dal informacije o picerijah, o oddelkih. Oddelek je skupina picerij, ki jih vodi en franšizojemalec.

  • ReceivingOrdersService je sprejel in izračunal sestavo naročila.

  • In SmsService je poslal SMS tako, da je poklical storitve API za pošiljanje SMS.

Storitve obdelujejo podatke iz podatkovne baze, hranijo poslovno logiko. Vsaka storitev je imela enega ali več *Repozitorijev z ustreznim imenom. Vsebovali so že poizvedbe do shranjenih procedur v bazi podatkov in plast preslikav. Poslovne logike je bilo v skladiščih, še posebej veliko v tistih, ki so izdajale poročevalske podatke. ORM ni bil uporabljen, vsi so se zanašali na ročno napisan sql. 

Obstajala je tudi plast modela domene in običajnih pomožnih razredov, na primer razred Order, ki je shranil naročilo. Na istem mestu, v sloju, je bil pomočnik za pretvorbo prikazanega besedila glede na izbrano valuto.

Vse to lahko predstavlja tak model:

Zgodovina arhitekture Dodo IS: zgodnji monolit

Način naročila

Razmislite o poenostavljenem začetnem načinu ustvarjanja takega naročila.

Zgodovina arhitekture Dodo IS: zgodnji monolit

Sprva je bilo spletno mesto statično. Na njem so bile cene, na vrhu pa telefonska številka in napis "Če želite pico - pokličite številko in naročite." Za naročilo moramo implementirati preprost tok: 

  • Stranka obišče statično spletno mesto s cenami, izbere izdelke in pokliče številko, navedeno na spletnem mestu.

  • Stranka poimenuje izdelke, ki jih želi dodati k naročilu.

  • Navede svoj naslov in ime.

  • Operater sprejme naročilo.

  • Naročilo je prikazano v vmesniku za sprejeta naročila.

Vse se začne s prikazom menija. Prijavljen uporabnik-operater sprejema samo eno naročilo naenkrat. Zato se osnutek vozička lahko shrani v njegovo sejo (uporabnikova seja je shranjena v pomnilniku). Obstaja predmet Košarica, ki vsebuje izdelke in podatke o strankah.

Stranka poimenuje izdelek, operater klikne na + ob izdelku in zahteva se pošlje strežniku. Podatki o izdelku se izvlečejo iz baze podatkov in se podatki o izdelku dodajo v košarico.

Zgodovina arhitekture Dodo IS: zgodnji monolit

Obvestilo. Da, tukaj izdelka ne morete potegniti iz baze podatkov, ampak ga prenesti iz frontenda. Toda zaradi jasnosti sem pokazal natančno pot iz baze podatkov. 

Nato vnesite naslov in ime stranke. 

Zgodovina arhitekture Dodo IS: zgodnji monolit

Ko kliknete »Ustvari naročilo«:

  • Zahteva se pošlje v OrderController.SaveOrder().

  • Košarico dobimo s seje, izdelki so v količini, ki jo potrebujemo.

  • Košarico dopolnimo s podatki o naročniku in jih posredujemo metodi AddOrder razreda ReceivingOrderService, kjer se shranijo v bazo. 

  • Baza ima tabele z naročilom, sestavo naročila, stranko in vse je povezano.

  • Vmesnik za prikaz naročil gre in izvleče najnovejša naročila ter jih prikaže.

Novi moduli

Prevzem naročila je bil pomemben in nujen. Ne morete poslovati s pico, če nimate naročila za prodajo. Zato je sistem začel pridobivati ​​funkcionalnost - približno od leta 2012 do 2015. V tem času se je pojavilo veliko različnih blokov sistema, ki jih bom poklical moduli, v nasprotju s konceptom storitve ali izdelka. 

Modul je skupek funkcij, ki jih združuje nek skupni poslovni cilj. Hkrati pa so fizično v isti aplikaciji.

Module lahko imenujemo sistemski bloki. To je na primer modul za poročanje, skrbniški vmesniki, sledilnik hrane v kuhinji, avtorizacija. Vse to so različni uporabniški vmesniki, nekateri imajo celo različne vizualne sloge. Hkrati je vse v okviru ene aplikacije, enega tekočega procesa. 

Tehnično so bili moduli zasnovani kot Area (takšna ideja je ostala celo v jedro asp.net). Obstajale so ločene datoteke za sprednji del, modele in lastne razrede krmilnikov. Posledično se je sistem preoblikoval iz tega ...

Zgodovina arhitekture Dodo IS: zgodnji monolit

...v tole:

Zgodovina arhitekture Dodo IS: zgodnji monolit

Nekateri moduli so implementirani na ločenih mestih (izvedljivi projekt), zaradi popolnoma ločene funkcionalnosti in deloma zaradi nekoliko ločenega, bolj fokusiranega razvoja. To:

  • Stran - prva verzija spletno mesto dodopizza.ru.

  • izvoz: nalaganje poročil iz Dodo IS za 1C. 

  • osebje - osebni račun zaposlenega. Razvit je bil ločeno in ima lastno vstopno točko ter ločen dizajn.

  • fs — projekt za gostovanje statike. Kasneje smo se od tega oddaljili in vso statiko preselili na Akamai CDN. 

Ostali bloki so bili v aplikaciji BackOffice. 

Zgodovina arhitekture Dodo IS: zgodnji monolit

Razlaga imena:

  • Blagajna - Blagajna v restavraciji.

  • ShiftManager - vmesniki za vlogo "Shift Manager": operativna statistika prodaje picerije, možnost uvrščanja izdelkov na stop listo, spreminjanje vrstnega reda.

  • OfficeManager - vmesniki za vloge "Upravitelj picerije" in "Franšizojemalec". Tukaj so zbrane funkcije za postavitev picerije, njene promocije bonusov, sprejem in delo z zaposlenimi, poročila.

  • PublicScreens - vmesniki za televizorje in tablice, ki visijo v picerijah. Televizorji prikazujejo menije, informacije o oglaševanju, status naročila ob dostavi. 

Uporabili so skupno storitveno plast, skupni blok domenskega razreda Dodo.Core in skupno bazo. Včasih so lahko še vodili po prehodih drug do drugega. Vključno s posameznimi spletnimi mesti, kot sta dodopizza.ru ali personal.dodopizza.ru, so šli v splošne storitve.

Ko so se pojavili novi moduli, smo poskušali čim bolj ponovno uporabiti že izdelano kodo storitev, shranjenih procedur in tabel v bazi. 

Za boljše razumevanje obsega modulov, izdelanih v sistemu, je tukaj diagram iz leta 2012 z razvojnimi načrti:

Zgodovina arhitekture Dodo IS: zgodnji monolit

Do leta 2015 je bilo vse na zemljevidu in še več je bilo v proizvodnji.

  • Sprejemanje naročil je preraslo v ločen blok Kontaktnega centra, kjer naročilo sprejema operater.

  • V picerijah so viseli javni zasloni z meniji in informacijami.

  • Kuhinja ima modul, ki avtomatsko predvaja glasovno sporočilo "Nova pica" ob novem naročilu, izpiše pa tudi račun za kurirja. To močno poenostavlja procese v kuhinji, zaposlenim omogoča, da jih ne moti veliko število preprostih operacij.

  • Dostavna enota je postala ločena Dostavna blagajna, kjer je bilo naročilo izdano kurirju, ki je prej prevzel izmeno. Njegov delovni čas je bil upoštevan pri obračunu plač. 

Vzporedno se je od leta 2012 do 2015 pojavilo več kot 10 razvijalcev, odprlo se je 35 picerij, namestilo sistem v Romunijo in se pripravilo na odprtje prodajnih mest v ZDA. Razvijalci se niso več ukvarjali z vsemi nalogami, ampak so bili razdeljeni v ekipe. vsak je specializiran za svoj del sistema. 

Težave

Tudi zaradi arhitekture (pa ne samo).

Kaos v bazi

Ena podlaga je priročna. V njej je mogoče doseči konsistentnost, in to na račun orodij, vgrajenih v relacijske baze podatkov. Delo z njim je znano in priročno, še posebej, če je malo tabel in malo podatkov.

Toda v 4 letih razvoja se je izkazalo, da ima baza podatkov približno 600 tabel, 1500 shranjenih procedur, od katerih so mnoge imele tudi logiko. Žal, shranjene procedure ne prinašajo veliko prednosti pri delu z MySQL. Baza jih ne predpomni, shranjevanje logike v njih pa otežuje razvoj in odpravljanje napak. Težavna je tudi ponovna uporaba kode.

Veliko tabel ni imelo ustreznih indeksov, nekje, nasprotno, je bilo veliko indeksov, kar je oteževalo vstavljanje. Treba je bilo spremeniti približno 20 tabel - transakcija za ustvarjanje naročila je lahko trajala približno 3-5 sekund. 

Podatki v tabelah niso bili vedno v najprimernejši obliki. Nekje je bilo treba narediti denormalizacijo. Del redno prejetih podatkov je bil v stolpcu v obliki strukture XML, kar je podaljšalo čas izvajanja, podaljšalo poizvedbe in otežilo razvoj.

Za iste mize so bile izdelane zelo heterogene zahteve. Priljubljene tabele so še posebej trpele, kot je zgoraj omenjena tabela. naročila ali mize picerija. Uporabljali so jih za prikaz operativnih vmesnikov v kuhinji, analitiko. Drugo spletno mesto je vzpostavilo stik z njimi (dodopizza.ru), kamor lahko v danem trenutku nenadoma pride veliko zahtev. 

Podatki niso bili združeni in veliko izračunov je potekalo sproti z uporabo baze. To je povzročilo nepotrebne izračune in dodatno obremenitev. 

Pogosto je koda šla v bazo podatkov, ko tega ni mogla storiti. Nekje ni bilo dovolj masovnih operacij, nekje bi bilo treba eno zahtevo prek kode razširiti na več, da bi pospešili in povečali zanesljivost. 

Kohezija in zamegljenost v kodi

Moduli, ki naj bi bili odgovorni za svoj del posla, tega niso delali pošteno. Nekateri od njih so imeli podvajanje funkcij za vloge. Na primer, lokalni tržnik, ki je odgovoren za marketinško dejavnost mreže v svojem mestu, je moral uporabiti tako vmesnik "Admin" (za ustvarjanje promocij) kot vmesnik "Office Manager" (za ogled vpliva promocij na podjetje). Seveda sta znotraj obeh modulov uporabljala isto storitev, ki je delovala z bonus promocijami.

Storitve (razredi znotraj enega monolitnega velikega projekta) bi lahko klicale druga drugo, da bi obogatile svoje podatke.

S samimi modelnimi razredi, ki shranjujejo podatke, delo v kodi je potekalo drugače. Nekje so bili konstruktorji, preko katerih je bilo mogoče določiti zahtevana polja. Nekje se je to izvajalo prek javne lastnine. Seveda je bilo pridobivanje in preoblikovanje podatkov iz baze pestro. 

Logika je bila ali v krmilnikih ali pa v servisnih razredih. 

Zdi se, da so to manjše težave, vendar so močno upočasnile razvoj in zmanjšale kakovost, kar je povzročilo nestabilnost in napake. 

Kompleksnost velikega razvoja

Težave so se pojavile pri samem razvoju. Treba je bilo narediti različne bloke sistema in vzporedno. Ujemanje potreb vsake komponente v eno samo kodo je postalo vse težje. Ni se bilo lahko dogovoriti in ugoditi vsem komponentam hkrati. Temu so bile dodane tehnološke omejitve, zlasti glede osnove in sprednjega dela. Treba je bilo opustiti jQuery v smeri visokonivojskih ogrodij, predvsem v smislu storitev za stranke (spletna stran).

V nekaterih delih sistema bi lahko uporabili za to primernejše baze podatkov.. Na primer, kasneje smo imeli primer uporabe, ko smo se iz Redisa preselili v CosmosDB za shranjevanje košarice naročil. 

Ekipe in razvijalci, vključeni v svoje področje, so očitno želeli več avtonomije za svoje storitve, tako v smislu razvoja kot uvajanja. Spojite spore, sprostite težave. Če je za 5 razvijalcev ta problem nepomemben, potem bi z 10, še bolj pa z načrtovano rastjo, vse postalo resnejše. In pred nami je bil razvoj mobilne aplikacije (začel se je leta 2017, leta 2018 pa je bil velik padec). 

Različni deli sistema so zahtevali različne stopnje stabilnosti, vendar zaradi močne povezljivosti sistema tega nismo mogli zagotoviti. Napaka pri razvoju nove funkcije v skrbniški plošči bi se lahko zgodila pri sprejemanju naročila na spletnem mestu, ker je koda običajna in jo je mogoče ponovno uporabiti, baza podatkov in podatki pa so enaki.

Verjetno bi se v okviru takšne monolitno-modularne arhitekture dalo izogniti tem napakam in težavam: narediti razdelitev odgovornosti, refaktorirati tako kodo kot bazo, jasno ločiti plasti med seboj, spremljati kakovost vsak dan. Toda izbrane arhitekturne rešitve in usmerjenost v hitro širitev funkcionalnosti sistema so povzročile težave na področju stabilnosti.

Kako je blog Power of the Mind postavil blagajne v restavracije

Če bi se rast mreže picerij (in obremenitev) nadaljevala z enako hitrostjo, bi bili čez nekaj časa padci takšni, da se sistem ne bi dvignil. Dobro ponazarja težave, s katerimi smo se začeli soočati leta 2015, tukaj je taka zgodba. 

V blogu "Moč uma” je bil widget, ki je prikazoval podatke o prihodkih za leto celotnega omrežja. Pripomoček je dostopal do javnega API-ja Dodo, ki zagotavlja te podatke. Ta statistika je trenutno na voljo na http://dodopizzastory.com/. Pripomoček je bil prikazan na vsaki strani in je vsakih 20 sekund pošiljal zahteve na časovniku. Zahteva je šla na api.dodopizza.ru in zahtevala:

  • število picerij v omrežju;

  • skupni prihodek omrežja od začetka leta;

  • prihodek za danes.

Zahteva po statistiki prihodkov je šla naravnost v bazo in začela zahtevati podatke o naročilih, sproti združevati podatke in izdajati znesek. 

Blagajne v restavracijah so šle na isto tabelo z naročili, razložile seznam naročil, prejetih za danes, in dodale so mu nova naročila. Blagajne so zahtevale vsakih 5 sekund ali ob osveževanju strani.

Diagram je izgledal takole:

Zgodovina arhitekture Dodo IS: zgodnji monolit

Neke jeseni je Fjodor Ovčinnikov na svojem blogu napisal dolg in priljubljen članek. Veliko ljudi je prišlo na blog in začelo vse pozorno brati. Medtem ko je vsak od ljudi, ki so prišli, bral članek, je pripomoček za prihodke deloval pravilno in zahteval API vsakih 20 sekund.

API je poklical shranjeno proceduro za izračun vsote vseh naročil od začetka leta za vse picerije v omrežju. Združevanje je temeljilo na tabeli naročil, ki je zelo priljubljena. K njej gredo vse blagajne vseh takrat odprtih restavracij. Blagajne so se nehale odzivati, naročila niso sprejemali. Prav tako niso bili sprejeti s strani, niso se pojavili na sledilniku, vodja izmene jih ni mogel videti v svojem vmesniku. 

To ni edina zgodba. Do jeseni 2015 je bila vsak petek obremenitev sistema kritična. Večkrat smo izklopili javni API, enkrat pa smo celo morali izklopiti stran, ker ni nič pomagalo. Obstajal je celo seznam storitev z ukazom za zaustavitev pod velikimi obremenitvami.

Od zdaj naprej se začne naš boj z obremenitvami in za stabilizacijo sistema (od jeseni 2015 do jeseni 2018). Takrat se je zgodilo"velik padec". Poleg tega so se včasih pojavljale tudi okvare, nekatere so bile zelo občutljive, a splošno obdobje nestabilnosti lahko štejemo za mimo.

Hitra rast poslovanja

Zakaj tega ni bilo mogoče narediti takoj? Samo poglejte naslednje grafikone.

Zgodovina arhitekture Dodo IS: zgodnji monolit

Tudi v letih 2014-2015 je bila otvoritev v Romuniji, pripravljala pa se je otvoritev v ZDA.

Mreža je zelo hitro rasla, odprle so se nove države, pojavili so se novi formati picerij, na primer picerija je bila odprta na igrišču s hrano. Vse to je zahtevalo veliko pozornosti posebej za razširitev funkcij Dodo IS. Brez vseh teh funkcij, brez sledenja v kuhinji, obračunavanja izdelkov in izgub v sistemu, prikaza izdaje naročila v gostinski dvorani težko govorimo o »pravilni« arhitekturi in »pravilnem« pristopu k razvoj zdaj.

Druga ovira za pravočasno revizijo arhitekture in na splošno pozornost tehničnim težavam je bila kriza leta 2014. Takšne stvari močno prizadenejo priložnosti za rast ekip, zlasti za mlado podjetje, kot je Dodo Pizza.

Hitre rešitve, ki so pomagale

Težave so potrebovale rešitve. Konvencionalno lahko rešitve razdelimo v 2 skupini:

  • Hitri, ki pogasijo ogenj in dajo majhno rezervo varnosti ter nam prikupijo čas, da se spremenimo.

  • Sistemsko in zato dolgo. Reinženiring številnih modulov, razdelitev monolitne arhitekture na ločene storitve (večina sploh ni mikro, ampak makro storitve, in nekaj je na tem Poročilo Andreja Morevskega). 

Suhi seznam hitrih sprememb je naslednji:

Povečajte osnovni mojster

Seveda je prva stvar, ki jo naredimo za reševanje obremenitev, povečanje zmogljivosti strežnika. To je bilo narejeno za glavno bazo podatkov in za spletne strežnike. Aja, to je možno le do neke meje, potem postane predrago.

Od leta 2014 smo se preselili na Azure, o tej temi smo takrat pisali tudi v članku “Kako Dodo Pizza dostavlja pico z uporabo oblaka Microsoft Azure". Toda po vrsti povečanj strežnika za osnovo so naleteli na stroške. 

Osnovne replike za branje

Za osnovo sta bili izdelani dve repliki:

ReadReplica za referenčne zahteve. Uporablja se za branje imenikov, tipov, mest, ulic, picerij, izdelkov (počasi spremenjena domena) in v tistih vmesnikih, kjer je sprejemljiva majhna zamuda. Teh replik sta bili 2, dobavljivost smo zagotovili na enak način kot mojstri.

ReadReplica za zahteve za poročilo. Ta zbirka podatkov je bila manj dostopna, vendar so šla vsa poročila vanjo. Naj imajo velike zahteve za velike preračune podatkov, vendar ne vplivajo na glavno bazo podatkov in operativne vmesnike. 

Predpomnilniki v kodi

Nikjer v kodi (sploh) ni bilo predpomnilnikov. To je vodilo do dodatnih, ne vedno potrebnih, zahtev za naloženo bazo podatkov. Predpomnilniki so bili najprej tako v pomnilniku kot v zunanji storitvi predpomnilnika, to je bil Redis. Vse je razveljavil čas, nastavitve so bile navedene v kodi.

Več zalednih strežnikov

Zaledje aplikacije je bilo treba tudi prilagoditi povečano delovno obremenitev. Iz enega iis-strežnika je bilo potrebno narediti gručo. Prestavili smo termin prijavna seja iz pomnilnika v RedisCache, kar je omogočilo izdelavo več strežnikov za preprostim izenačevalnikom obremenitve s krožnim robom. Sprva je bil isti Redis uporabljen kot za predpomnilnike, nato pa so ga razdelili na več. 

Zaradi tega je arhitektura postala bolj zapletena ...

Zgodovina arhitekture Dodo IS: zgodnji monolit

… vendar je bilo nekaj napetosti odpravljeno.

In potem je bilo treba naložene komponente predelati, česar smo se lotili. O tem bomo govorili v naslednjem delu.

Vir: www.habr.com

Dodaj komentar