Povijest Dodo IS arhitekture: rani monolit

Ili je svaka nesretna tvrtka s monolitom nesretna na svoj način.

Razvoj Dodo IS sustava započeo je odmah, poput Dodo Pizza biznisa - 2011. godine. Temeljio se na ideji potpune i potpune digitalizacije poslovnih procesa, te sam, koji je i tada 2011. godine izazvao mnoga pitanja i skepticizam. Ali već 9 godina idemo tim putem - vlastitim razvojem koji je započeo s monolitom.

Ovaj članak je “odgovor” na pitanja “Zašto prepravljati arhitekturu i raditi tako velike i dugoročne promjene?” na prethodni članak “Povijest Dodo IS arhitekture: put pozadinskog ureda”. Počet ću s time kako je počeo razvoj Dodo IS-a, kako je izgledala početna arhitektura, kako su se pojavili novi moduli i zbog kojih je problema bilo potrebno napraviti velike promjene.

Povijest Dodo IS arhitekture: rani monolit

Serija članaka "Što je Dodo IS?" govori o:

  1. Rani monolit u Dodo IS (2011.-2015.). (Ti si ovdje)

  2. Put do ureda: odvojene baze i autobus.

  3. Put sa strane klijenta: fasada preko baze (2016-2017). (U nastajanju...)

  4. Povijest pravih mikroservisa. (2018.-2019.). (U nastajanju...)

  5. Završeno piljenje monolita i stabilizacija arhitekture. (U nastajanju...)

Primordijalna arhitektura

2011. Dodo IS arhitektura je izgledala ovako:

Povijest Dodo IS arhitekture: rani monolit

Prvi modul u arhitekturi je prihvat narudžbi. Poslovni proces je bio ovakav:

  • kupac zove pizzeriju;

  • Upravitelj podiže slušalicu;

  • prima narudžbe putem telefona;

  • Istodobno ga popunjava u sučelju za prihvaćanje narudžbi: uzimaju se u obzir podaci o klijentu, podaci o detaljima narudžbe i adresa dostave. 

Sučelje informacijskog sustava izgledalo je otprilike ovako...

Prva verzija iz listopada 2011.:

Neznatno poboljšan u siječnju 2012

Informacijski sustav Dodo Pizza Delivery Pizza Restaurant

Resursi za razvoj prvog modula za primanje narudžbi bili su ograničeni. Trebalo je napraviti puno, brzo i s malom ekipom. Mali tim se sastoji od 2 programera koji su postavili temelje za cijeli budući sustav.

Njihova prva odluka odredila je buduću sudbinu tehnološkog niza:

  • Pozadina na ASP.NET MVC, C# jeziku. Programeri su bili dotnetteri; ovaj im je skup bio poznat i ugodan.

  • Frontend na Bootstrapu i JQueryju: korisnička sučelja temeljena na prilagođenim stilovima i skriptama. 

  • MySQL baza podataka: nema troškova licence, jednostavna za korištenje.

  • Poslužitelji na Windows Serveru, jer je .NET tada mogao biti samo na Windowsima (nećemo raspravljati o Mono).

Fizički, sve je to bilo izraženo u “domaćinskom stolu”. 

Arhitektura aplikacije za prihvaćanje naloga

Tada su već svi pričali o mikroservisima, a SOA se koristila u velikim projektima oko 5 godina, primjerice WCF je izašao 2006. godine. Ali onda su odabrali pouzdano i provjereno rješenje.

Evo ga.

Povijest Dodo IS arhitekture: rani monolit

Asp.Net MVC je Razor, koji na zahtjev obrasca ili klijenta proizvodi HTML stranicu s renderiranjem na poslužitelju. Na klijentu CSS i JS skripte već prikazuju informacije i po potrebi izvode AJAX zahtjeve putem JQueryja.

Zahtjevi na poslužitelju spadaju u klase *Controller, gdje metoda obrađuje i generira konačnu HTML stranicu. Kontroleri podnose zahtjeve sloju logike koji se zove *Services. Svaka od usluga odgovarala je nekom aspektu poslovanja:

  • Na primjer, DepartmentStructureService pružio je informacije o pizzerijama i odjelima. Odjel je skupina pizzerija kojima upravlja jedan primatelj franšize.

  • ReceivingOrdersService primio je i izračunao sadržaj narudžbe.

  • I SmsService je poslao SMS pozivom API servisa za slanje SMS-a.

Servisi su obrađivali podatke iz baze i pohranjivali poslovnu logiku. Svaki servis je imao jedno ili više *Repozitorija s odgovarajućim nazivom. Već su sadržavali upite pohranjenim procedurama u bazi podataka i sloj mapera. Repozitoriji su imali poslovnu logiku, osobito mnogi od njih koji su proizvodili podatke za izvješća. ORM se nije koristio, svi su se oslanjali na rukom pisani sql. 

Postojao je i sloj modela domene i općih pomoćnih klasa, na primjer klasa Order, koja je pohranjivala red. Tamo, u sloju, nalazio se pomoćnik za pretvorbu prikaza teksta prema odabranoj valuti.

Sve se to može prikazati ovim modelom:

Povijest Dodo IS arhitekture: rani monolit

Način narudžbe

Razmotrimo pojednostavljeni početni način stvaranja takvog naloga.

Povijest Dodo IS arhitekture: rani monolit

U početku je stranica bila statična. Na njemu su bile cijene, a na vrhu je stajao broj telefona i natpis “Ako želite pizzu, nazovite broj i naručite”. Da bismo naručili, moramo implementirati jednostavan tijek: 

  • Klijent odlazi na statičnu web stranicu s cijenama, odabire proizvode i poziva broj naveden na web stranici.

  • Kupac imenuje proizvode koje želi dodati narudžbi.

  • Daje svoju adresu i ime.

  • Operater prihvaća narudžbu.

  • Narudžba se prikazuje u sučelju prihvaćenih narudžbi.

Sve počinje prikazom izbornika. Prijavljeni korisnik operater prihvaća samo jednu narudžbu odjednom. Stoga se nacrt košarice može pohraniti u njegovu sesiju (korisnička sesija pohranjuje se u memoriju). Postoji objekt Cart koji sadrži proizvode i informacije o kupcima.

Klijent imenuje proizvod, operater klikne na + pored proizvoda, a zahtjev se šalje poslužitelju. Podaci o proizvodu se izvlače iz baze i podaci o proizvodu se dodaju u košaricu.

Povijest Dodo IS arhitekture: rani monolit

Primijetiti. Da, ovdje ne morate izvlačiti proizvod iz baze podataka, već ga prenijeti s prednje strane. Ali radi jasnoće, pokazao sam točno put od baze. 

Zatim unesite adresu i ime klijenta. 

Povijest Dodo IS arhitekture: rani monolit

Kada kliknete na "Izradi narudžbu":

  • Šaljemo zahtjev na OrderController.SaveOrder().

  • Dobivamo košaricu sa sesije, ima proizvoda u količini koja nam je potrebna.

  • Košaricu dopunjujemo podacima o klijentu i prosljeđujemo ih metodi AddOrder klase ReceivingOrderService, gdje se spremaju u bazu podataka. 

  • Baza podataka ima tablice s nalogom, sadržajem naloga, klijentom i sve je povezano.

  • Sučelje za prikaz naloga ide i izvlači najnovije naloge te ih prikazuje.

Novi moduli

Primanje narudžbe bilo je važno i potrebno. Ne možete voditi posao s pizzom ako nemate narudžbu za prodaju. Stoga je sustav počeo stjecati funkcionalnost - otprilike od 2012. do 2015. godine. Tijekom tog vremena pojavilo se mnogo različitih blokova sustava, koje ću nazvati moduli, za razliku od koncepta usluge ili proizvoda. 

Modul je skup funkcija koje su objedinjene nekim zajedničkim poslovnim ciljem. Štoviše, fizički se nalaze u istoj aplikaciji.

Moduli se mogu nazvati sistemskim blokovima. Na primjer, ovo je modul za izvješćivanje, administrativna sučelja, pratilac kuhinjskih proizvoda, ovlaštenje. Sve su to različita korisnička sučelja, neka čak imaju različite vizualne stilove. Štoviše, sve je unutar jedne aplikacije, jednog pokrenutog procesa. 

Tehnički, moduli su dizajnirani kao Area (ova ideja je čak ostala u asp.net jezgra). Postojale su zasebne datoteke za sučelje, modele, kao i vlastite klase kontrolera. Kao rezultat toga, sustav je transformiran iz takvog...

Povijest Dodo IS arhitekture: rani monolit

... na ovo:

Povijest Dodo IS arhitekture: rani monolit

Neki moduli su implementirani na zasebnim stranicama (izvršni projekt), zbog potpuno odvojene funkcionalnosti, a dijelom i zbog donekle odvojenog, usmjerenijeg razvoja. Ovaj:

  • mjesto - prva verzija web stranica dodopizza.ru.

  • Izvoz: preuzimanje izvješća iz Dodo IS za 1C. 

  • osoblje - osobni račun zaposlenika. Razvijen je zasebno i ima vlastitu ulaznu točku i poseban dizajn.

  • fs — projekt za statički hosting. Kasnije smo se udaljili od toga, premjestivši sav statični sadržaj na Akamai CDN. 

Preostali blokovi nalazili su se u BackOffice aplikaciji. 

Povijest Dodo IS arhitekture: rani monolit

Objašnjenje imena:

  • Blagajna - blagajna restorana.

  • ShiftManager - sučelja za ulogu “Shift Manager”: operativna statistika prodaje pizzerije, mogućnost stavljanja proizvoda na stop listu, promjena narudžbe.

  • OfficeManager - sučelja za uloge “Upravitelj pizzerije” i “Primatelj franšize”. Ovdje možete pronaći funkcije za postavljanje pizzerije, njezine bonus promocije, primanje i rad sa zaposlenicima te izvješća.

  • PublicScreens - sučelja za televizore i tablete koji vise u pizzerijama. Televizori prikazuju jelovnik, reklamne informacije i status narudžbe nakon isporuke. 

Koristili su zajednički servisni sloj, zajednički blok domenskih klasa Dodo.Core i zajedničku bazu. Ponekad su ipak mogli voditi kroz prolaze jedan do drugoga. Osim toga, pojedinačne stranice, poput dodopizza.ru ili personal.dodopizza.ru, također su pristupale zajedničkim uslugama.

Kada su se pojavili novi moduli, pokušali smo što je više moguće ponovno koristiti već kreirani kod za usluge, pohranjene procedure i tablice u bazi podataka. 

Za bolje razumijevanje razmjera modula izrađenih u sustavu, evo dijagrama iz 2012. godine s planovima razvoja:

Povijest Dodo IS arhitekture: rani monolit

Do 2015. sve je bilo na pravom putu, a još više je bilo u proizvodnji.

  • Prihvat narudžbi prerastao je u zaseban blok Kontakt centra, gdje narudžbe prima operater.

  • U pizzerijama su se pojavili javni zasloni s jelovnicima i informacijama.

  • Kuhinja ima modul koji automatski pušta glasovnu poruku “Nova pizza” kada stigne nova narudžba, a ispisuje i račun za kurira. To uvelike pojednostavljuje procese u kuhinji i omogućuje zaposlenicima da ne budu ometani velikim brojem jednostavnih operacija.

  • Dostavni blok postao je zasebna Dostavna blagajna, gdje se narudžba izdavala kuriru, koji je prethodno preuzeo svoju smjenu. Njegovo radno vrijeme uzeto je u obzir za obračun plaće. 

Paralelno, od 2012. do 2015. pojavilo se više od 10 programera, otvoreno 35 pizzerija, sustav je implementiran u Rumunjsku i pripremljen za otvaranje točaka u SAD-u. Programeri više nisu bili uključeni u sve zadatke, već su bili podijeljeni u timove. svaki specijaliziran za svoj dio sustava. 

Problemi

Uključujući i zbog arhitekture (ali ne samo).

Kaos u bazi

Jedna baza je prikladna. Moguće je postići konzistentnost i nauštrb alata ugrađenih u relacijske baze podataka. Rad s njim je poznat i zgodan, pogotovo ako ima malo tablica i malo podataka.

Ali tijekom 4 godine razvoja, baza podataka je sadržavala oko 600 tablica, 1500 pohranjenih procedura, od kojih su mnoge imale i logiku. Nažalost, pohranjene procedure ne pružaju mnogo koristi pri radu s MySQL-om. Baza ih ne sprema u predmemoriju, a pohranjivanje logike u njih komplicira razvoj i otklanjanje pogrešaka. Ponovno korištenje koda također je teško.

Mnoge tablice nisu imale odgovarajuće indekse, negdje je, naprotiv, bilo puno indeksa, što je otežavalo umetanje. Oko 20 tablica je moralo biti izmijenjeno—transakcija za stvaranje narudžbe mogla je trajati oko 3-5 sekundi. 

Podaci u tablicama nisu uvijek bili u najprikladnijem obliku. Negdje je bilo potrebno napraviti denormalizaciju. Dio redovito zaprimljenih podataka bio je u stupcu u obliku XML strukture, što je produžilo vrijeme izvršenja, produžilo upite i kompliciralo razvoj.

Iste tablice bile su predmet vrlo heterogenih zahtjeva. Popularne tablice, poput gore spomenute, bile su posebno pogođene narudžbe ili tablice picerija. Korišteni su za prikaz operativnih sučelja u kuhinji i analitici. Stranica ih je također kontaktirala (dodopizza.ru), gdje bi puno zahtjeva moglo iznenada stići u bilo kojem trenutku. 

Podaci nisu agregirani a mnogi su se izračuni odvijali u hodu pomoću baze. To je stvorilo nepotrebne izračune i dodatno opterećenje. 

Često je kod otišao u bazu podataka kada to nije mogao učiniti. Negdje je nedostajalo skupnih operacija, negdje bi bilo potrebno jedan zahtjev razdvojiti na nekoliko kroz kod kako bi se ubrzalo i povećala pouzdanost. 

Kohezija i konfuzija u kodu

Moduli koji su trebali biti odgovorni za svoj dio posla nisu to radili pošteno. Neki od njih imali su dupliciranje funkcija za uloge. Na primjer, lokalni trgovac koji je odgovoran za marketinšku aktivnost mreže u svom gradu morao je koristiti i sučelje "Administrator" (za postavljanje promocija) i sučelje "Upravitelj ureda" (za pregled utjecaja promocija na poslovanje). Naravno, unutar oba modula koristila se ista usluga, koja je radila s bonus promocijama.

Servisi (klase unutar jednog monolitnog velikog projekta) mogu se međusobno pozivati ​​kako bi obogatili svoje podatke.

Sa samim klasama modela koje pohranjuju podatke, rad u kodu odvijao se drugačije. Negdje su postojali konstruktori preko kojih ste mogli specificirati potrebna polja. Negdje se to radilo putem javnih posjeda. Naravno, dobivanje i transformiranje podataka iz baze bilo je raznoliko. 

Logika je bila ili u kontrolerima ili servisnim klasama. 

Čini se da su to manji problemi, ali su uvelike usporili razvoj i smanjili kvalitetu, što je dovelo do nestabilnosti i grešaka. 

Složenost velikog razvoja

Poteškoće su se javile u samom razvoju. Bilo je potrebno kreirati različite blokove sustava, i to paralelno. Postalo je sve teže uklopiti potrebe svake komponente u jedan kod. Nije bilo lako složiti se i zadovoljiti sve komponente u isto vrijeme. Tome su pridodana ograničenja u tehnologiji, posebice u pogledu baze i prednjeg kraja. Bilo je potrebno napustiti JQuery u korist okvira visoke razine, posebno u pogledu usluga klijentima (web stranica).

Neki dijelovi sustava mogli bi koristiti baze podataka koje su za to prikladnije. Na primjer, kasnije smo imali presedan za prebacivanje s Redisa na CosmosDB za pohranu košarice za narudžbu. 

Timovi i programeri koji rade u svom području jasno su željeli više neovisnosti za svoje usluge, kako u smislu razvoja tako i u smislu uvođenja. Sukobi tijekom spajanja, problemi tijekom izdanja. Ako je za 5 programera ovaj problem beznačajan, onda bi s 10, a još više s planiranim rastom, sve postalo ozbiljnije. A tek je uslijedio razvoj mobilne aplikacije (počeo je 2017., a 2018. veliki pad). 

Različiti dijelovi sustava zahtijevali su različite pokazatelje stabilnosti, no zbog jake povezanosti sustava to nismo mogli pružiti. Pogreška prilikom razvijanja nove funkcije u administratorskoj ploči mogla je rezultirati prihvaćanjem narudžbe na stranici, jer je kod uobičajen i može se ponovno koristiti, baza podataka i podaci također su isti.

Vjerojatno bi bilo moguće izbjeći te greške i probleme u okviru takve monolitno-modularne arhitekture: stvoriti razdvajanje odgovornosti, refaktorirati i kod i bazu podataka, jasno odvojiti slojeve jedne od drugih i pratiti kvalitetu svaki dan. Ali odabrana arhitektonska rješenja i fokus na brzo proširenje funkcionalnosti sustava doveli su do problema u pogledu stabilnosti.

Kako je blog Power of Mind stavio blagajne u restorane

Kad bi se rast mreže (i opterećenja) pizzeria nastavio istim tempom, onda bi nakon nekog vremena padovi bili takvi da se sustav ne bi oporavio. Sljedeća priča dobro ilustrira probleme s kojima smo se počeli suočavati 2015. godine. 

U blogu "Snaga uma"postojao je widget koji je prikazivao podatke o prihodu za godinu za cijelu mrežu. Widget je pristupio javnom Dodo API-ju, koji pruža ove podatke. Ove su statistike sada dostupne na http://dodopizzastory.com/. Widget se prikazivao na svakoj stranici i slao je zahtjeve na mjeraču vremena svakih 20 sekundi. Zahtjev je otišao na api.dodopizza.ru i pitao:

  • broj pizzerija u mreži;

  • ukupni mrežni prihod od početka godine;

  • današnji prihod.

Zahtjev za statistiku prihoda otišao je ravno u bazu podataka i počeo tražiti podatke o narudžbama, agregirati podatke izravno u hodu i izdavati iznos. 

Blagajne u restoranima išle su na istu tablicu narudžbi, učitavale listu prihvaćenih narudžbi za danas te su joj dodavale nove narudžbe. Blagajne su svoje zahtjeve postavljale svakih 5 sekundi ili kad je stranica osvježena.

Dijagram je izgledao ovako:

Povijest Dodo IS arhitekture: rani monolit

Jednog dana u jesen, Fjodor Ovčinnikov je napisao dug i popularan članak na svom blogu. Puno je ljudi došlo na blog i počelo sve pažljivo čitati. Dok je svatko od ljudi koji su došli čitao članak, widget prihoda radio je ispravno i zahtijevao API svakih 20 sekundi.

API je nazvao pohranjenu proceduru za izračun iznosa svih narudžbi od početka godine za sve pizzerije u mreži. Agregacija se temeljila na tablici narudžbi, koja je vrlo popularna. Na njega idu sve blagajne svih u to vrijeme otvorenih restorana. Blagajne su prestale reagirati i narudžbe se nisu primale. Također nisu prihvaćeni sa stranice, nisu se pojavili na trackeru, a voditelj smjene ih nije mogao vidjeti u svom sučelju. 

Ovo nije jedina priča. Do jeseni 2015., svakog petka opterećenje sustava bilo je kritično. Nekoliko puta smo isključili javni API, a jednom smo čak morali isključiti stranicu jer ništa nije pomoglo. Postojao je čak i popis usluga s redoslijedom gašenja pod velikim opterećenjem.

Od ovog trenutka počinje naša borba s opterećenjem i stabilizacijom sustava (od jeseni 2015. do jeseni 2018.). Tada se to dogodilo"Veliki pad" Nadalje, ponekad je bilo i kvarova, od kojih su neki bili vrlo osjetljivi, no opće razdoblje nestabilnosti sada se može smatrati završenim.

Brz poslovni rast

Zašto se nije moglo "odmah dobro napraviti"? Pogledajte samo sljedeće grafikone.

Povijest Dodo IS arhitekture: rani monolit

Također 2014.-2015. bilo je otvorenje u Rumunjskoj, au pripremi je bilo otvaranje u SAD-u.

Lanac je vrlo brzo rastao, otvarale su se nove zemlje, pojavili su se novi formati pizzerija, na primjer, pizzerija je otvorena u food courtu. Sve je to zahtijevalo značajnu pozornost upravo na proširenju funkcija Dodo IS-a. Bez svih ovih funkcija, bez praćenja u kuhinji, obračunavanja proizvoda i gubitaka u sustavu, prikaza dostave narudžbi u dvorani s hranom, malo je vjerojatno da bismo sada govorili o „ispravnoj“ arhitekturi i „ispravnoj“ ” pristup razvoju.

Još jedna prepreka pravodobnoj reviziji arhitekture i općenitom obraćanju pažnje na tehničke probleme bila je kriza iz 2014. godine. Takve stvari štete mogućnostima rasta timova, posebno za mladu tvrtku kao što je Dodo Pizza.

Brza rješenja koja su pomogla

Problemi su zahtijevali rješenja. Konvencionalno, rješenja se mogu podijeliti u 2 skupine:

  • One brze koje gase vatru i daju nam malu sigurnost i kupuju nam vrijeme da se promijenimo.

  • Sustavno i, stoga, dugo. Reinženjering niza modula, dijeljenje monolitne arhitekture na zasebne servise (većina njih nisu mikro, već makro servisi, a o tome više izvješće Andreja Morevskog). 

Suha lista brzih promjena je:

Povećaj osnovni glavni

Naravno, prva stvar koja se radi u borbi protiv opterećenja je povećanje snage poslužitelja. To je učinjeno za glavnu bazu podataka i web poslužitelje. Nažalost, to je moguće samo do određene granice; preko toga postaje preskupo.

Od 2014. smo prešli na Azure, o ovoj temi smo također pisali tada u članku “Kako Dodo Pizza dostavlja pizzu koristeći Microsoft Azure oblak" Ali nakon niza povećanja poslužitelja, cijena baze dosegla je granicu. 

Replike baze podataka za čitanje

Napravili smo dvije replike za bazu:

ReadReplica za zahtjeve imenika. Koristi se za čitanje imenika, kao što su grad, ulica, pizzerija, proizvodi (polako promijenjena domena), te u onim sučeljima gdje je prihvatljivo malo kašnjenje. Bilo je 2 ove replike, osigurali smo njihovu dostupnost na isti način kao i majstor.

ReadReplica za zahtjeve izvješća. Ova baza podataka bila je manje dostupna, ali su sva izvješća išla u nju. Oni mogu imati teške zahtjeve za ogromnim ponovnim izračunima podataka, ali ne utječu na glavnu bazu podataka i operativna sučelja. 

Predmemorije u kodu

Nigdje u kodu (uopće) nije bilo predmemorije. To je dovelo do dodatnih, ne uvijek potrebnih zahtjeva za učitanu bazu podataka. U početku su predmemorije bile i u memoriji i na vanjskoj usluzi predmemorije, bio je to Redis. Sve je vremenski nevažeće, postavke su navedene u kodu.

Više poslužitelja za backend

Pozadina aplikacije također je morala biti skalirana kako bi izdržala povećana opterećenja. Bilo je potrebno napraviti klaster od jednog IIS servera. Preselili smo se prijavna sesija iz memorije na RedisCacheu, što je omogućilo stvaranje nekoliko poslužitelja iza jednostavnog balansera opterećenja s kružnim radom. Isprva je korišten isti Redis kao i za spremišta, a zatim su podijeljeni u nekoliko. 

Kao rezultat toga, arhitektura je postala složenija...

Povijest Dodo IS arhitekture: rani monolit

...ali dio napetosti je popustio.

A onda je bilo potrebno preraditi učitane komponente, što smo mi preuzeli. O tome ćemo govoriti u sljedećem dijelu.

Izvor: www.habr.com

Dodajte komentar