Istorija Dodo IS arhitekture: rani monolit

Ili je svaka nesretna kompanija sa monolitom nesretna na svoj način.

Razvoj Dodo IS sistema je počeo odmah, kao i Dodo Pizza biznis, 2011. godine. Zasnovan je na ideji potpune i totalne digitalizacije poslovnih procesa, i samostalno, što je i tada 2011. izazvalo mnogo pitanja i skepse. Ali već 9 godina idemo ovim putem - vlastitim razvojem koji je započeo monolitom.

Ovaj članak je “odgovor” na pitanja “Zašto prepisivati ​​arhitekturu i praviti tako velike i dugoročne promjene?” nazad na prethodni članak "Istorija Dodo IS arhitekture: Put pozadinskog ureda". Počeću od toga kako je počeo razvoj Dodo IS-a, kako je izgledala originalna arhitektura, kako su se pojavili novi moduli i zbog kojih problema su se morale napraviti velike promene.

Istorija Dodo IS arhitekture: rani monolit

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

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

  2. Putanja pozadinske kancelarije: odvojene baze i sabirnica.

  3. Putanja na strani klijenta: fasada preko baze (2016-2017). (U toku...)

  4. Istorija pravih mikroservisa. (2018-2019). (U toku...)

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

Početna arhitektura

Godine 2011. Dodo IS arhitektura je izgledala ovako:

Istorija Dodo IS arhitekture: rani monolit

Prvi modul u arhitekturi je prihvatanje naloga. Poslovni proces je bio:

  • klijent zove piceriju;

  • menadžer podiže slušalicu;

  • prima narudžbu telefonom;

  • ispunjava ga paralelno u interfejsu za prihvatanje narudžbi: uzima u obzir podatke o klijentu, podatke o detaljima narudžbe, adresu za dostavu. 

Interfejs informacionog sistema izgledao je otprilike ovako...

Prva verzija iz oktobra 2011:

Malo poboljšan u januaru 2012

Dodo Pizza Informacijski sistem Dostava Pizza restoran

Resursi za razvoj modula za primanje prve narudžbe bili su ograničeni. Morali smo mnogo da uradimo, brzo i sa malim timom. Mali tim čine 2 programera koji su postavili temelje za cijeli budući sistem.

Njihova prva odluka odredila je sudbinu tehnološkog paketa:

  • Backend na ASP.NET MVC, C# jeziku. Programeri su bili dotnetchiki, ovaj stack im je bio poznat i prijatan.

  • Frontend na Bootstrapu i JQueryju: korisnički interfejsi na stilovima i skriptama koje sami pišu. 

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

  • Serveri na Windows Serveru, jer bi .NET tada mogao biti samo pod Windowsom (nećemo raspravljati o Mono).

Fizički, sve je to bilo izraženo u “dediću kod hostera”. 

Arhitektura aplikacije za unos naloga

Tada su već svi pričali o mikroservisima, a SOA se koristila u velikim projektima 5 godina, na primjer, WCF je objavljen 2006. Ali tada su odabrali pouzdano i provjereno rješenje.

Evo ga.

Istorija Dodo IS arhitekture: rani monolit

Asp.Net MVC je Razor, koji, na zahtjev iz obrasca ili od klijenta, prikazuje HTML stranicu sa serverskim renderiranjem. Na klijentu, CSS i JS skripte već prikazuju informacije i, ako je potrebno, izvode AJAX zahtjeve kroz JQuery.

Zahtjevi na serveru završavaju u klasama *Controller, gdje se obrada i generiranje konačne HTML stranice odvija u metodi. Kontroleri postavljaju zahtjeve sloju logike koji se zove *Services. Svaka od usluga je odgovarala nekom aspektu poslovanja:

  • Na primjer, DepartmentStructureService je davao informacije o pizzerijama, o odjelima. Odjel je grupa picerija koje vodi jedan korisnik franšize.

  • ReceivingOrdersService je prihvatio i izračunao sastav narudžbe.

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

Usluge obrađuju podatke iz baze podataka, pohranjuju poslovnu logiku. Svaki servis je imao jedno ili više *Repozitorija sa odgovarajućim imenom. Oni su već sadržavali upite za pohranjene procedure u bazi podataka i sloj mapera. U skladištima je bilo poslovne logike, posebno mnogo u onima koje su izdavale izvještajne podatke. ORM nije korišten, svi su se oslanjali na rukom pisani sql. 

Postojao je i sloj modela domene i uobičajenih pomoćnih klasa, na primjer klasa Order koja je pohranila nalog. Na istom mjestu, u sloju, nalazio se pomoćnik za konverziju teksta na ekranu prema odabranoj valuti.

Sve se to može predstaviti ovakvim modelom:

Istorija Dodo IS arhitekture: rani monolit

Order Way

Razmotrite pojednostavljeni početni način kreiranja takvog naloga.

Istorija Dodo IS arhitekture: rani monolit

U početku je stranica bila statična. Na njemu su bile cijene, a na vrhu - broj telefona i natpis "Ako želite picu - zovite broj i naručite". Da bismo naručili, moramo implementirati jednostavan tok: 

  • Klijent posjećuje statičnu stranicu s cijenama, bira proizvode i zove broj naveden na stranici.

  • Kupac imenuje proizvode koje želi dodati u narudžbu.

  • Daje njegovu adresu i ime.

  • Operater prihvata narudžbu.

  • Narudžba je prikazana u interfejsu prihvaćenih naloga.

Sve počinje prikazivanjem menija. Prijavljeni korisnik-operater prihvaća samo jednu narudžbu u isto vrijeme. Dakle, nacrt kolica se može pohraniti u njegovoj sesiji (korisnička sesija je pohranjena u memoriji). Postoji objekt Cart koji sadrži informacije o proizvodima i kupcima.

Kupac imenuje proizvod, operater klikne na + pored proizvoda, a zahtjev se šalje serveru. Podaci o proizvodu se izvlače iz baze podataka i podaci o proizvodu se dodaju u korpu.

Istorija Dodo IS arhitekture: rani monolit

primjedba. Da, ovdje ne možete izvući proizvod iz baze podataka, već ga prenijeti sa frontenda. Ali radi jasnoće, pokazao sam tačno putanju iz baze podataka. 

Zatim unesite adresu i ime klijenta. 

Istorija Dodo IS arhitekture: rani monolit

Kada kliknete na "Kreiraj narudžbu":

  • Zahtjev se šalje na OrderController.SaveOrder().

  • Sa sesije dobijamo korpu, ima proizvoda u količini koja nam je potrebna.

  • Dopunjavamo košaricu informacijama o klijentu i prosljeđujemo je metodi AddOrder klase ReceivingOrderService, gdje se pohranjuje u bazu podataka. 

  • Baza ima tabele sa nalogom, sastavom naloga, klijentom i sve su povezane.

  • Interfejs za prikaz naloga ide i izvlači najnovije narudžbe i prikazuje ih.

Novi moduli

Preuzimanje narudžbe bilo je važno i neophodno. Ne možete raditi pizza posao ako nemate narudžbu za prodaju. Stoga je sistem počeo dobivati ​​funkcionalnost - otprilike od 2012. do 2015. godine. Za to vrijeme pojavilo se mnogo različitih blokova sistema, koje ću nazvati moduli, za razliku od koncepta usluge ili proizvoda. 

Modul je skup funkcija koje su objedinjene nekim zajedničkim poslovnim ciljem. U isto vrijeme, oni su fizički u istoj aplikaciji.

Moduli se mogu nazvati sistemskim blokovima. Na primjer, ovo je modul za izvještavanje, administratorska sučelja, tragač hrane u kuhinji, autorizacija. Sve su to različiti korisnički interfejsi, neki čak imaju različite vizuelne stilove. Istovremeno, sve je u okviru jedne aplikacije, jednog pokrenutog procesa. 

Tehnički, moduli su dizajnirani kao Area (takva ideja je čak ostala asp.net core). Postojali su zasebni fajlovi za frontend, modele, kao i sopstvene klase kontrolera. Kao rezultat, sistem je transformisan iz ovog ...

Istorija Dodo IS arhitekture: rani monolit

...u ovo:

Istorija Dodo IS arhitekture: rani monolit

Neki moduli su implementirani na zasebnim lokacijama (izvršni projekat), zbog potpuno odvojene funkcionalnosti i dijelom zbog malo odvojenog, fokusiranijeg razvoja. Ovo:

  • site - prva verzija stranica dodopizza.ru.

  • izvoz: postavljanje izvještaja iz Dodo IS-a za 1C. 

  • Lični - lični račun zaposlenog. Razvijen je zasebno i ima svoju ulaznu tačku i poseban dizajn.

  • fs — projekat za hostovanje statike. Kasnije smo se udaljili od toga, premjestivši svu statiku na Akamai CDN. 

Ostali blokovi su bili u BackOffice aplikaciji. 

Istorija Dodo IS arhitekture: rani monolit

Objašnjenje imena:

  • Blagajnik - Blagajnik restorana.

  • ShiftManager - sučelja za ulogu "Shift Manager": operativna statistika o prodaji picerije, mogućnost stavljanja proizvoda na stop listu, promjena redoslijeda.

  • OfficeManager - sučelja za uloge "Menadžer picerije" i "Primalac franšize". Ovdje su prikupljene funkcije za postavljanje picerije, njene bonus promocije, primanje i rad sa zaposlenicima, izvještaji.

  • PublicScreens - interfejsi za televizore i tablete koji vise u pizzerijama. Televizori prikazuju menije, reklamne informacije, status narudžbe po isporuci. 

Koristili su zajednički servisni sloj, zajednički blok klase domene Dodo.Core i zajedničku bazu. Ponekad su ipak mogli voditi duž prijelaza jedan do drugog. Uključujući pojedinačne sajtove, kao što su dodopizza.ru ili personal.dodopizza.ru, otišao je na opšte usluge.

Kada su se pojavili novi moduli, pokušali smo maksimalno iskoristiti već kreirani kod servisa, pohranjenih procedura i tabela u bazi podataka. 

Za bolje razumijevanje obima modula napravljenih u sistemu, evo dijagrama iz 2012. godine sa razvojnim planovima:

Istorija Dodo IS arhitekture: rani monolit

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

  • Prijem porudžbina je prerastao u poseban blok Kontakt centra, gdje narudžbu prima operater.

  • U picerijama su visili javni ekrani sa menijima i informacijama.

  • Kuhinja ima modul koji automatski pušta glasovnu poruku "Nova pica" kada stigne nova porudžbina, a takođe ispisuje račun za kurira. To uvelike pojednostavljuje procese u kuhinji, omogućava zaposlenima da ne budu ometani velikim brojem jednostavnih operacija.

  • Jedinica za dostavu postala je zasebna blagajna za dostavu, gdje se narudžba izdavala kuriru koji je prethodno preuzeo smjenu. Njegovo radno vrijeme je uzeto u obzir za obračun plata. 

Paralelno, od 2012. do 2015. pojavilo se više od 10 developera, otvorilo se 35 picerija, implementiralo sistem u Rumuniju i pripremilo se za otvaranje prodajnih mjesta u Sjedinjenim Državama. Programeri se više nisu bavili svim zadacima, već su bili podijeljeni u timove. svaki je specijalizovan za svoj dio sistema. 

Problemi

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

Haos u bazi

Jedna baza je pogodna. U njemu se može postići konzistentnost i to na račun alata ugrađenih u relacijske baze podataka. Rad s njim je poznat i zgodan, posebno ako ima malo tabela i malo podataka.

Ali tokom 4 godine razvoja, pokazalo se da baza podataka ima oko 600 tabela, 1500 uskladištenih procedura, od kojih su mnoge takođe imale logiku. Nažalost, pohranjene procedure ne donose veliku prednost pri radu sa MySQL-om. Baza ih ne kešira, a skladištenje logike u njima komplicira razvoj i otklanjanje grešaka. Ponovna upotreba koda je takođe teška.

Mnoge tabele nisu imale odgovarajuće indekse, negdje je, naprotiv, bilo puno indeksa, što je otežavalo umetanje. Bilo je potrebno modificirati oko 20 tabela - transakcija za kreiranje naloga mogla je potrajati oko 3-5 sekundi. 

Podaci u tabelama nisu uvijek bili u najprikladnijoj formi. Negdje je trebalo napraviti denormalizaciju. Dio redovno primljenih podataka bio je u koloni u obliku XML strukture, što je povećalo vrijeme izvršenja, produžilo upite i zakomplikovalo razvoj.

Za iste su stolovi proizvedeni vrlo heterogenih zahteva. Posebno su stradali popularni stolovi, poput gore pomenute. narudžbe ili tablice picerija. Korišćeni su za prikaz operativnih interfejsa u kuhinji, analitike. Druga stranica ih je kontaktirala (dodopizza.ru), gdje bi u svakom trenutku odjednom moglo doći mnogo zahtjeva. 

Podaci nisu agregirani i mnogi proračuni su se odvijali u hodu koristeći bazu. To je stvorilo nepotrebne proračune i dodatno opterećenje. 

Često je kod odlazio u bazu podataka kada to nije mogao učiniti. Negdje nije bilo dovoljno masovnih operacija, negdje bi bilo potrebno raširiti jedan zahtjev na nekoliko kroz kod kako bi se ubrzala i povećala pouzdanost. 

Kohezija i zamagljivanje u kodu

Moduli koji su trebali biti odgovorni za svoj dio posla nisu to radili pošteno. Neki od njih su imali dupliranje funkcija za uloge. Na primjer, lokalni marketer koji je odgovoran za marketinške aktivnosti mreže u svom gradu morao je koristiti i "Admin" interfejs (za kreiranje promocija) i interfejs "Office Manager" (da vidi uticaj promocija na poslovanje). Naravno, unutar oba modula korišten je isti servis koji je radio sa bonus promocijama.

Servisi (klase u okviru jednog monolitnog velikog projekta) mogu zvati jedni druge da obogate svoje podatke.

Sa samim klasama modela koje pohranjuju podatke, rad u kodu se odvijao drugačije. Negdje su postojali konstruktori preko kojih je bilo moguće specificirati tražena polja. Negdje se to radilo preko javnih dobara. Naravno, dobijanje i transformacija podataka iz baze podataka bilo je raznoliko. 

Logika je bila ili u kontrolerima ili u 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 pojavile u samom razvoju. Bilo je potrebno napraviti različite blokove sistema, i to paralelno. Uklapanje potreba svake komponente u jedan kod postajalo je sve teže. Nije bilo lako dogovoriti se i zadovoljiti sve komponente u isto vrijeme. Ovome su dodana ograničenja u tehnologiji, posebno u pogledu baze i frontenda. Bilo je neophodno napustiti jQuery u pravcu okvira visokog nivoa, posebno u pogledu klijentskih usluga (web stranica).

U nekim dijelovima sistema mogu se koristiti baze podataka koje su pogodnije za ovo.. Na primjer, kasnije smo imali slučaj korištenja prelaska sa Redisa na CosmosDB za pohranjivanje korpe za narudžbu. 

Timovi i programeri uključeni u svoju oblast jasno su željeli više autonomije za svoje usluge, kako u smislu razvoja tako i uvođenja. Spojite sukobe, oslobodite probleme. Ako je za 5 programera ovaj problem beznačajan, onda bi s 10, a još više s planiranim rastom, sve postalo ozbiljnije. A pred nama je bio razvoj mobilne aplikacije (počeo je 2017., a 2018. veliki pad). 

Različiti dijelovi sistema zahtijevali su različite nivoe stabilnosti, ali zbog jake povezanosti sistema ovo nismo mogli pružiti. Do greške u izradi nove funkcije u admin panelu je moglo doći i u prihvatanju narudžbe na sajtu, jer je kod uobičajen i za višekratnu upotrebu, baza i podaci su takođe isti.

Vjerovatno bi bilo moguće izbjeći ove greške i probleme u okviru takve monolitno-modularne arhitekture: napraviti podjelu odgovornosti, refaktorirati i kod i bazu podataka, jasno odvojiti slojeve jedan od drugog, pratiti kvalitetu svaki dan. Ali odabrana arhitektonska rješenja i fokus na brzo širenje funkcionalnosti sistema doveli su do problema u pogledu stabilnosti.

Kako je blog Power of the Mind postavio kase u restorane

Kada bi se rast mreže picerija (i opterećenja) nastavio istim tempom, onda bi nakon nekog vremena padovi bili takvi da se sistem ne bi dizao. Dobro ilustruje probleme sa kojima smo počeli da se suočavamo do 2015. godine, evo jedne takve priče. 

Na blogu "Snaga uma” je bio widget koji je prikazivao podatke o prihodima za godinu cijele mreže. Vidžet je pristupio Dodo javnom API-ju, koji pruža ove podatke. Ova statistika je trenutno dostupna na http://dodopizzastory.com/. Vidžet je bio prikazan na svakoj stranici i postavljao je zahtjeve na tajmeru svakih 20 sekundi. Zahtjev je otišao na api.dodopizza.ru i tražio:

  • broj picerija u mreži;

  • ukupan prihod mreže od početka godine;

  • prihod za danas.

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

Blagajne u restoranima išle su na istu tabelu narudžbi, istovarile listu narudžbi za danas, a na nju su dodavane nove narudžbe. Kase su davale svoje zahtjeve svakih 5 sekundi ili na osvježavanju stranice.

Dijagram je izgledao ovako:

Istorija Dodo IS arhitekture: rani monolit

Jedne jeseni, Fjodor Ovčinikov je napisao dugačak i popularan članak na svom blogu. Mnogo ljudi je došlo na blog i počelo sve pažljivo čitati. Dok je svaki od ljudi koji je došao čitao članak, widget prihoda je radio ispravno i tražio je API svakih 20 sekundi.

API je pozvao pohranjenu proceduru za izračunavanje sume svih narudžbi od početka godine za sve picerije u lancu. Agregacija je bazirana na tabeli narudžbi, koja je veoma popularna. U njega idu sve blagajne svih tada otvorenih restorana. Blagajne su prestale da odgovaraju, narudžbe nisu primane. Oni također nisu prihvaćeni sa stranice, nisu se pojavili na trackeru, menadžer smjene ih nije mogao vidjeti u svom interfejsu. 

Ovo nije jedina priča. Do jeseni 2015., svakog petka opterećenje sistema je bilo kritično. Nekoliko puta smo isključili javni API, a jednom smo čak morali isključiti i stranicu, jer ništa nije pomoglo. Postojala je čak i lista usluga sa nalogom za gašenje pod velikim opterećenjem.

Od sada počinje naša borba sa opterećenjima i za stabilizaciju sistema (od jeseni 2015. do jeseni 2018.). Tada se to desilo"odličan pad". Nadalje, ponekad su se dešavali i kvarovi, neki su bili vrlo osjetljivi, ali se opći period nestabilnosti sada može smatrati prošlim.

Brz rast poslovanja

Zašto se to nije moglo uraditi odmah? Samo pogledajte sljedeće grafikone.

Istorija Dodo IS arhitekture: rani monolit

Takođe 2014-2015 bilo je otvaranje u Rumuniji i priprema se otvaranje u SAD.

Mreža je vrlo brzo rasla, otvarale su se nove zemlje, pojavili su se novi formati picerija, na primjer, otvorena je picerija u restoranu. Sve je to zahtijevalo značajnu pažnju posebno na proširenje Dodo IS funkcija. Bez svih ovih funkcija, bez praćenja u kuhinji, obračuna proizvoda i gubitaka u sistemu, prikazivanja izdavanja naloga u sali restorana, teško da bismo govorili o „ispravnoj“ arhitekturi i „ispravnom“ pristupu razvoj sada.

Još jedna prepreka pravovremenoj reviziji arhitekture i općenito obraćanju pažnje na tehničke probleme bila je kriza iz 2014. godine. Ovakve stvari su teško pogodile prilike za razvoj timova, posebno za mlad biznis kao što je Dodo Pizza.

Brza rješenja koja su pomogla

Problemi potrebna rješenja. Uobičajeno, rješenja se mogu podijeliti u 2 grupe:

  • Brzi koji gase vatru i daju malu marginu sigurnosti i kupuju nam vremena za promjenu.

  • Sistemski i stoga dugotrajni. Reinženjering većeg broja modula, podjela monolitne arhitekture na zasebne servise (većina njih uopće nisu mikro, već makro servisi, i ima nešto u tome Izveštaj Andreja Morevskog). 

Suha lista brzih izmjena je sljedeća:

Povećajte osnovni master

Naravno, prva stvar koja se radi da se nosi sa opterećenjem je povećanje kapaciteta servera. Ovo je urađeno za glavnu bazu podataka i za web servere. Jao, to je moguće samo do određene granice, a onda postaje preskupo.

Od 2014. godine prešli smo na Azure, o ovoj temi smo pisali i tada u članku “Kako Dodo Pizza isporučuje pizzu koristeći Microsoft Azure oblak". Ali nakon niza povećanja servera za bazu, naišli su na cijenu. 

Osnovne replike za čitanje

Za bazu su napravljene dvije replike:

ReadReplica za referentne zahtjeve. Koristi se za čitanje imenika, tipa, grada, ulice, picerije, proizvoda (sporo promijenjen domen), te u onim interfejsima gdje je malo kašnjenje prihvatljivo. Ove replike su bile 2, njihovu dostupnost smo osigurali na isti način kao i majstori.

Pročitaj repliku za zahtjeve za izvješće. Ova baza podataka je bila manje dostupna, ali su svi izvještaji išli u nju. Neka imaju teške zahtjeve za ogromnim ponovnim proračunima podataka, ali oni ne utiču na glavnu bazu podataka i operativna sučelja. 

Keširanje u kodu

Nije bilo keša nigde u kodu (uopšte). To je dovelo do dodatnih, ne uvijek neophodnih, zahtjeva za učitanu bazu podataka. Kešovi su prvo bili i u memoriji i na eksternom keš servisu, to je bio Redis. Sve je poništeno vremenom, postavke su navedene u kodu.

Više backend servera

Pozadinu aplikacije je također trebalo skalirati kako bi se nosila s povećanim radnim opterećenjem. Bilo je potrebno napraviti klaster od jednog iis-servera. Ponovo smo zakazali sesija aplikacije iz memorije u RedisCache, što je omogućilo da se napravi nekoliko servera iza jednostavnog balansera opterećenja sa round robin. Isprva se koristio isti Redis kao i za keš memorije, a zatim je podijeljen na nekoliko. 

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

Istorija Dodo IS arhitekture: rani monolit

… ali dio napetosti je uklonjen.

A onda je bilo potrebno preraditi učitane komponente, što smo i poduzeli. O tome ćemo govoriti u narednom dijelu.

izvor: www.habr.com

Dodajte komentar