Архитектонска историја на Додо е: ран монолит

Или секоја несреќна компанија со монолит е несреќна на свој начин.

Развојот на системот Dodo IS започна веднаш, како бизнисот Dodo Pizza - во 2011 година. Се засноваше на идејата за целосна и целосна дигитализација на деловните процеси и самостојно, што и тогаш во 2011 година покрена многу прашања и скептицизам. Но, веќе 9 години одиме по овој пат - со сопствен развој, кој започна со монолит.

Оваа статија е „одговор“ на прашањата „Зошто да се преработи архитектурата и да се прават толку големи и долгорочни промени?“ на претходната статија „Историјата на архитектурата Додо ИС: патека на задната канцеларија“. Ќе започнам со тоа како започна развојот на Dodo IS, како изгледаше почетната архитектура, како се појавија новите модули и поради кои проблеми требаше да се направат големи промени.

Архитектонска историја на Додо е: ран монолит

Серија написи „Што е Додо ИС? ќе каже за:

  1. Ран монолит во Додо ИС (2011-2015). (Ти си тука)

  2. Backoffice патека: посебни бази и автобус.

  3. Патека на клиентскиот дел: фасада над основата (2016-2017). (Во тек...)

  4. Историјата на вистинските микроуслуги. (2018-2019). (Во тек...)

  5. Завршено сечење на монолитот и стабилизација на архитектурата. (Во тек...)

Примордијална архитектура

Во 2011 година, архитектурата Додо ИС изгледаше вака:

Архитектонска историја на Додо е: ран монолит

Првиот модул во архитектурата е прифаќање на нарачки. Деловниот процес беше вака:

  • клиент се јавува во пицеријата;

  • Менаџерот го крева телефонот;

  • прима нарачки преку телефон;

  • Во исто време, го пополнува во интерфејсот за прифаќање нарачки: се земаат предвид информациите за клиентот, податоците за деталите за нарачката и адресата за испорака. 

Интерфејсот на информацискиот систем изгледаше отприлика вака...

Првата верзија од октомври 2011 година:

Малку подобрена во јануари 2012 година

Информациски систем Додо Пица Достава Пица Ресторан

Ресурсите за развивање на модулот за преземање прва нарачка беа ограничени. Требаше да се направи многу, брзо и со мал тим. Малиот тим се состои од 2 програмери кои ги поставија темелите за целиот иден систем.

Нивната прва одлука ја одреди идната судбина на технолошкиот куп:

  • Backend на ASP.NET MVC, јазик C#. Програмерите беа точки; овој оџак им беше познат и пријатен.

  • Frontend на Bootstrap и JQuery: кориснички интерфејси базирани на сопствени стилови и скрипти. 

  • MySQL база на податоци: без трошоци за лиценца, лесен за користење.

  • Сервери на Windows Server, бидејќи .NET тогаш можеше да биде само на Windows (нема да разговараме за Mono).

Физички, сето тоа беше изразено во „бирото на домаќинот“. 

Архитектура на апликацијата за прифаќање нарачка

Во тоа време, сите веќе зборуваа за микроуслуги, а SOA се користеше во големи проекти околу 5 години, на пример, WCF беше објавен во 2006 година. Но, тогаш тие избраа сигурно и докажано решение.

Еве го.

Архитектонска историја на Додо е: ран монолит

Asp.Net MVC е Razor, кој, на барање од формулар или од клиент, произведува HTML страница со рендерирање на серверот. На клиентот, CSS и JS скриптите веќе прикажуваат информации и, доколку е потребно, извршуваат AJAX барања преку JQuery.

Барањата на серверот спаѓаат во класите *Controller, каде што методот ја обработува и генерира конечната HTML страница. Контролорите поднесуваат барања до логички слој наречен *Услуги. Секоја од услугите одговараше на некој аспект од бизнисот:

  • На пример, DepartmentStructureService обезбеди информации за пицериите и одделенијата. Оддел е група пицерии управувани од еден франшиза.

  • ReceivingOrdersService ја прими и ја пресмета содржината на нарачката.

  • И SmsService испрати СМС со повикување на услугите на API за испраќање СМС.

Услугите обработувале податоци од базата на податоци и ја складирале деловната логика. Секоја услуга имаше едно или повеќе *Репозиториуми со соодветно име. Тие веќе содржеа барања за складирани процедури во базата на податоци и слој од мапери. Складиштата имаа деловна логика, особено многу од нив што произведуваа податоци за известување. ОРМ не се користеше, сите се потпираа на рачно напишано sql. 

Имаше и слој од моделот на доменот и општите помошни класи, на пример, класата Order, која ја складираше нарачката. Таму, во слојот, имаше помошник за конвертирање на текстот на екранот според избраната валута.

Сето ова може да се претстави со овој модел:

Архитектонска историја на Додо е: ран монолит

Начин на нарачка

Ајде да разгледаме поедноставен почетен начин за создавање таков редослед.

Архитектонска историја на Додо е: ран монолит

Првично локацијата беше статична. На него имаше цени, а на врвот имаше телефонски број и натпис „Ако сакате пица, јавете се на бројот и нарачајте“. За да нарачаме, треба да спроведеме едноставен тек: 

  • Клиентот оди на статична веб-локација со цени, избира производи и се јавува на бројот наведен на веб-страницата.

  • Клиентот ги именува производите што сака да ги додаде во нарачката.

  • Ја дава својата адреса и име.

  • Операторот ја прифаќа нарачката.

  • Нарачката се прикажува во интерфејсот за прифатени нарачки.

Сè започнува со приказот на менито. Најавен корисник на оператор прифаќа само една нарачка во исто време. Затоа, нацрт-количката може да се зачува во нејзината сесија (сесијата на корисникот е зачувана во меморијата). Постои објект Кошничка што содржи производи и информации за клиентите.

Клиентот го именува производот, операторот кликнува на + веднаш до производот и се испраќа барање до серверот. Информациите за производот се извлекуваат од базата на податоци и информациите за производот се додаваат во количката.

Архитектонска историја на Додо е: ран монолит

Имајте на ум. Да, тука не треба да го извлекувате производот од базата на податоци, туку да го пренесете од предниот дел. Но, за јасност, ја покажав точно патеката од основата. 

Следно, внесете ја адресата и името на клиентот. 

Архитектонска историја на Додо е: ран монолит

Кога ќе кликнете на „Креирај нарачка“:

  • Барањето го испраќаме до OrderController.SaveOrder().

  • Добиваме кошничка од сесијата, има производи во количина што ни треба.

  • Ја дополнуваме Количката со информации за клиентот и ја пренесуваме на методот AddOrder од класата ReceivingOrderService, каде што се зачувува во базата на податоци. 

  • Базата на податоци има табели со нарачката, содржината на нарачката, клиентот и сите тие се поврзани.

  • Интерфејсот за прикажување нарачки оди и ги вади најновите нарачки и ги прикажува.

Нови модули

Примањето на нарачката беше важно и неопходно. Не можете да водите бизнис со пица ако немате нарачка за продажба. Затоа, системот почна да добива функционалност - од приближно 2012 до 2015 година. За тоа време се појавија многу различни блокови на системот, кои ќе ги наречам модули, наспроти концептот на услуга или производ. 

Модул е ​​збир на функции кои се обединети со некоја заедничка деловна цел. Покрај тоа, тие се физички лоцирани во истата апликација.

Модулите може да се наречат системски блокови. На пример, ова е модул за известување, административни интерфејси, тракер за кујнски производи, овластување. Сите овие се различни кориснички интерфејси, некои дури имаат различни визуелни стилови. Покрај тоа, сè е во една апликација, еден процес кој работи. 

Технички, модулите беа дизајнирани како Површина (оваа идеја дури и остана во asp.net јадро). Имаше посебни датотеки за предниот дел, моделите, како и нивните класи на контролери. Како резултат на тоа, системот беше трансформиран од такви ...

Архитектонска историја на Додо е: ран монолит

...на ова:

Архитектонска историја на Додо е: ран монолит

Некои модули се имплементирани од посебни сајтови (извршен проект), поради целосно одвоена функционалност и делумно поради донекаде одделен, пофокусиран развој. Ова:

  • Мапа - првата верзија веб-страница dodopizza.ru.

  • Извоз: преземање извештаи од Dodo IS за 1C. 

  • Лична - лична сметка на вработениот. Тој беше развиен одделно и има своја влезна точка и посебен дизајн.

  • fs — проект за статичен хостинг. Подоцна се оддалечивме од него, преместувајќи ја целата статична содржина во Akamai CDN. 

Останатите блокови беа лоцирани во апликацијата BackOffice. 

Архитектонска историја на Додо е: ран монолит

Објаснување на имињата:

  • Касиерка - Каса во ресторан.

  • ShiftManager - интерфејси за улогата „Shift Manager“: оперативна статистика за продажба на пицерии, можност за ставање производи на список за стопирање, промена на нарачка.

  • OfficeManager - интерфејси за улогите „Менаџер на пицерија“ и „Франшиза“. Овде можете да најдете функции за поставување пицерија, нејзини бонус промоции, примање и работа со вработени и извештаи.

  • PublicScreens - интерфејси за телевизори и таблети кои висат во пицериите. Телевизорите го прикажуваат менито, информациите за рекламирање и статусот на нарачката при испораката. 

Тие користеа заеднички слој на услуги, заеднички блок од класи на домени Dodo.Core и заедничка база. Понекогаш тие сепак можеа да водат низ премини еден до друг. Покрај тоа, поединечни страници, како што се dodopizza.ru или personal.dodopizza.ru, исто така пристапуваа до заеднички услуги.

Кога се појавија нови модули, се обидовме да го реупотребиме што е можно повеќе веќе креираниот код за услуги, складирани процедури и табели во базата на податоци. 

За подобро разбирање на обемот на модулите направени во системот, еве дијаграм од 2012 година со планови за развој:

Архитектонска историја на Додо е: ран монолит

До 2015 година, сè беше на добар пат, а уште повеќе беше во производство.

  • Прифаќањето на нарачката прерасна во посебен блок на Контакт центарот, каде што нарачката ја прифаќа операторот.

  • Во пицериите се појавија јавни екрани со менија и информации.

  • Кујната има модул кој автоматски репродуцира говорна порака „Нова пица“ кога ќе пристигне нова нарачка, а исто така печати фактура за курир. Ова во голема мера ги поедноставува процесите во кујната и им овозможува на вработените да не се одвлекуваат од голем број едноставни операции.

  • Блокот за испорака стана посебен Касиер за испорака, каде што нарачката беше издадена на курир, кој претходно ја презеде смената. За пресметување на платата му било земено предвид работното време. 

Паралелно, од 2012 до 2015 година, се појавија повеќе од 10 програмери, отворени 35 пицерии, системот беше распореден во Романија и подготвен за отворање на точки во САД. Програмерите повеќе не беа вклучени во сите задачи, туку беа поделени во тимови. секој специјализиран за свој дел од системот. 

Проблеми

Вклучително и поради архитектурата (но не само).

Хаос во основата

Една основа е погодна. Можно е да се постигне конзистентност, а на сметка на алатки вградени во релациони бази на податоци. Работата со него е позната и удобна, особено ако има малку табели и малку податоци.

Но, во текот на 4 години развој, базата на податоци содржеше околу 600 табели, 1500 складирани процедури, од кои многу имаа и логика. За жал, складираните процедури не даваат голема корист кога работите со MySQL. Тие не се кеширани од базата на податоци, а складирањето логика во нив го комплицира развојот и дебагирањето. Повторната употреба на кодот е исто така тешка.

Многу табели немаа соодветни индекси, некаде, напротив, имаше многу индекси, што го отежнуваше вметнувањето. Требаше да се изменат околу 20 табели - трансакцијата за создавање нарачка може да трае околу 3-5 секунди. 

Податоците во табелите не беа секогаш во најсоодветната форма. Некаде требаше да се направи денормализација. Некои од редовно примените податоци беа во колона во форма на XML структура, што го зголеми времето на извршување, ги продолжи барањата и го комплицираше развојот.

Истите табели беа предмет на многу хетерогени барања. Популарните табели, како табелата спомената погоре, беа особено погодени нарачки или табели пицерија. Тие беа користени за прикажување на оперативните интерфејси во кујната и аналитиката. Сајтот исто така ги контактираше (dodopizza.ru), каде што многу барања може одеднаш да пристигнат во даден момент. 

Податоците не беа собрани и многу пресметки се случија во лет користејќи ја основата. Ова создаде непотребни пресметки и дополнително оптоварување. 

Честопати кодот влегуваше во базата на податоци кога не можеше да го стори тоа. Некаде недостигаа масовни операции, некаде ќе требаше да се подели едно барање на неколку преку код за да се забрза и зголеми доверливоста. 

Кохезија и конфузија во кодот

Модулите кои требаше да бидат одговорни за нивниот дел од бизнисот не го направија тоа искрено. Некои од нив имаа дуплирање на функции за улоги. На пример, локален продавач кој е одговорен за маркетинг активноста на мрежата во неговиот град мораше да ги користи и интерфејсот „Admin“ (за поставување промоции) и интерфејсот „Office Manager“ (за да го види влијанието на промоциите врз бизнис). Се разбира, во двата модула се користеше истата услуга, која работеше со бонус промоции.

Услугите (класите во рамките на еден монолитен голем проект) би можеле да се јават меѓусебно за да ги збогатат своите податоци.

Со самите класи на модели кои ги складираат податоците, работата во кодот беше извршена поинаку. Некаде имаше конструктори преку кои можеше да ги наведеш потребните полиња. Некаде тоа се правеше преку јавни имоти. Се разбира, добивањето и трансформирањето на податоците од базата на податоци беше различно. 

Логиката беше или во контролори или во сервисни класи. 

Овие изгледаат како помали проблеми, но во голема мера го забавија развојот и го намалија квалитетот, што доведе до нестабилност и грешки. 

Комплексност на голем развој

Се појавија тешкотии во самиот развој. Беше неопходно да се создадат различни блокови на системот, и паралелно. Стануваше сè потешко да се вклопат потребите на секоја компонента во единствен код. Не беше лесно да се договорат и да се задоволат сите компоненти во исто време. На ова беа додадени ограничувањата во технологијата, особено во однос на основата и предниот дел. Беше неопходно да се напушти JQuery во корист на рамки на високо ниво, особено во однос на услугите на клиентите (веб-страница).

Некои делови од системот би можеле да користат бази на податоци кои се посоодветни за ова. На пример, подоцна имавме преседан за префрлување од Redis на CosmosDB за складирање на количка за нарачки. 

Тимовите и програмерите кои работат во нивната област очигледно сакаа поголема независност за нивните услуги, како во однос на развојот, така и во однос на ширењето. Конфликти за време на спојувања, проблеми за време на изданија. Ако за 5 програмери овој проблем е незначителен, тогаш со 10, а уште повеќе со планираниот раст, сè би станало посериозно. А она што следуваше беше развој на мобилна апликација (започна во 2017 година, а во 2018 имаше голем пад). 

Различни делови од системот бараа различни индикатори за стабилност, но поради силната поврзаност на системот, не можевме да го обезбедиме ова. Грешка при развивање на нова функција во административниот панел може да резултира со прифаќање на нарачката на страницата, бидејќи кодот е вообичаен и може повторно да се користи, базата на податоци и податоците се исто така исти.

Веројатно би било можно да се избегнат овие грешки и проблеми во рамките на таквата монолитно-модуларна архитектура: да се создаде поделба на одговорностите, да се рефакторираат и кодот и базата на податоци, јасно да се одделат слоевите еден од друг и да се следи квалитетот секој ден. Но, избраните архитектонски решенија и фокусот на брзо проширување на функционалноста на системот доведоа до проблеми во однос на стабилноста.

Како блогот Power of Mind става каси во рестораните

Доколку растот на мрежата на пицериите (и оптоварувањето) продолжи со исто темпо, тогаш по некое време падовите би биле такви што системот нема да закрепне. Следната приказна добро ги илустрира проблемите со кои почнавме да се соочуваме до 2015 година. 

Во блогот“Моќ на умот„Имаше графичка контрола што ги прикажуваше податоците за приходите за годината за целата мрежа. Виџетот пристапи до јавното Dodo API, кое ги обезбедува овие податоци. Овие статистики сега се достапни на http://dodopizzastory.com/. Виџетот се прикажуваше на секоја страница и испраќаше барања на тајмер на секои 20 секунди. Барањето отиде на api.dodopizza.ru и праша:

  • број на пицерии во мрежата;

  • вкупен приход од мрежата од почетокот на годината;

  • денешниот приход.

Барањето за статистика на приходите отиде директно во базата на податоци и почна да бара податоци за нарачките, да ги собира податоците директно во лет и да ја издава сумата. 

Касите во рестораните отидоа на истата табела со нарачки, поставија список со прифатени нарачки за денеска, а на него беа додадени и нови нарачки. Касите ги поднесуваа своите барања на секои 5 секунди или кога се освежуваше страницата.

Дијаграмот изгледаше вака:

Архитектонска историја на Додо е: ран монолит

Еден ден наесен, Фјодор Овчиников напиша долга и популарна статија на својот блог. Многу луѓе дојдоа на блогот и почнаа да читаат сè внимателно. Додека секој од луѓето што дојдоа ја читаше статијата, додатокот за приходи работеше правилно и бараше API на секои 20 секунди.

API повика на складирана процедура за пресметување на износот на сите нарачки од почетокот на годината за сите пицерии во мрежата. Агрегацијата се базираше на табелата за нарачки, која е многу популарна. Кај него одат сите каси на сите отворени ресторани во тоа време. Касите престанаа да реагираат и нарачките не беа прифатени. Тие исто така не беа прифатени од страницата, не се појавија на тракерот, а менаџерот на смена не можеше да ги види во неговиот интерфејс. 

Ова не е единствената приказна. До есента 2015 година, секој петок оптоварувањето на системот беше критично. Неколку пати го исклучивме јавниот API, а еднаш дури и моравме да ја исклучиме страницата бидејќи ништо не помагаше. Имаше дури и список на услуги со редослед на исклучување при тешки товари.

Од овој момент започнува нашата борба со оптоварувањата и за стабилизација на системот (од есен 2015 до есен 2018 година). Тогаш се случи“Големиот пад" Понатаму, понекогаш имаше и неуспеси, од кои некои беа многу чувствителни, но општиот период на нестабилност сега може да се смета за завршен.

Брз раст на бизнисот

Зошто тоа не можеше „да се направи добро веднаш“? Само погледнете ги следните графикони.

Архитектонска историја на Додо е: ран монолит

Исто така во 2014-2015 година имаше отворање во Романија и се подготвуваше отворање во САД.

Синџирот порасна многу брзо, се отворија нови земји, се појавија нови формати на пицерии, на пример, отворена пицерија во судот за храна. Сето ова бараше значително внимание конкретно за проширување на функциите на Додо ИС. Без сите овие функции, без следење во кујната, сметководство за производи и загуби во системот, прикажување на испораката на нарачките во салата за храна, малку е веројатно дека сега би зборувале за „правилната“ архитектура и „точната „пристап кон развој.

Друга пречка за навремена ревизија на архитектурата и општо внимание на техничките проблеми беше кризата од 2014 година. Таквите работи ги повредуваат можностите за раст на тимовите, особено за млад бизнис како Додо пица.

Брзи решенија кои помогнаа

Проблемите бараа решенија. Конвенционално, решенијата можат да се поделат во 2 групи:

  • Брзи кои го гаснат огнот и ни даваат мала маргина на безбедност и ни купуваат време да се промениме.

  • Системски и, според тоа, долго. Реинженеринг на голем број модули, делење на монолитната архитектура на посебни услуги (повеќето од нив не се микро, туку макро услуги, и има повеќе за ова извештај на Андреј Моревски). 

Сувата листа на брзи промени е:

Зголемете го главниот господар на основата

Се разбира, првото нешто што се прави за борба против оптоварувањето е да се зголеми моќта на серверот. Ова беше направено за главната база на податоци и веб-сервери. За жал, ова е можно само до одредена граница, надвор од тоа станува прескапо.

Од 2014 година, се преселивме во Azure; исто така пишувавме за оваа тема тогаш во статијата “Како Dodo Pizza испорачува пица со помош на облакот Microsoft Azure" Но, по серијата зголемувања на серверот, цената на базата достигна граница. 

Реплики на бази на податоци за читање

Направивме две копии за основата:

ReadReplica за барања за директориум. Се користи за читање директориуми, како што се град, улица, пицерија, производи (полека променет домен) и во оние интерфејси каде што е прифатливо мало доцнење. Имаше 2 од овие реплики, ја обезбедивме нивната достапност на ист начин како мајсторот.

ReadReplica за барања за извештаи. Оваа база на податоци имаше помала достапност, но сите извештаи отидоа до неа. Тие може да имаат големи барања за огромни пресметки на податоци, но тие не влијаат на главната база на податоци и оперативните интерфејси. 

Кеш во кодот

Никаде во кодот немаше кешови (воопшто). Ова доведе до дополнителни, не секогаш неопходни, барања до вчитаната база на податоци. Отпрвин, кешовите беа и во меморија и на надворешна кеш услуга, тоа беше Redis. Сè беше временски поништено, поставките беа наведени во кодот.

Повеќе сервери за задниот дел

Задниот дел на апликацијата, исто така, мораше да биде намален за да издржи зголемени оптоварувања. Беше неопходно да се направи кластер од еден IIS сервер. Се преселивме сесија за апликација од меморијата на RedisCache, што овозможи да се создадат неколку сервери зад едноставен балансирач на оптоварување со тркалезна форма. Отпрвин се користеше истиот Редис како и за кешовите, а потоа беа поделени на неколку. 

Како резултат на тоа, архитектурата стана посложена ...

Архитектонска историја на Додо е: ран монолит

...но малку од тензијата се намали.

И тогаш беше неопходно повторно да се направат вчитаните компоненти, што е она што го презедовме. За ова ќе зборуваме во следниот дел.

Извор: www.habr.com

Додадете коментар