Монолиттен микросервиске көшу: тарих және тәжірибе

Бұл мақалада мен жұмыс істеп жатқан жобаның үлкен монолиттен микросервистердің жиынтығына қалай өзгергені туралы айтатын боламын.

Жоба өз тарихын біршама уақыт бұрын, 2000 жылдың басында бастады. Алғашқы нұсқалары Visual Basic 6-да жазылды. Уақыт өте келе бұл тілдегі дамуды болашақта қолдау қиын болатыны белгілі болды, өйткені IDE. ал тілдің өзі нашар дамыған. 2000 жылдардың соңында болашағы зор C# тіліне көшу туралы шешім қабылданды. Жаңа нұсқа ескінің қайта қаралуымен қатар жазылды, бірте-бірте .NET-те көбірек код жазылды. C# тіліндегі бэкэнд бастапқыда қызмет архитектурасына бағытталған, бірақ әзірлеу барысында логикасы бар жалпы кітапханалар пайдаланылды және қызметтер бір процесте іске қосылды. Нәтижесінде біз «қызмет монолиті» деп атаған қолданба пайда болды.

Бұл комбинацияның бірнеше артықшылықтарының бірі қызметтердің сыртқы API арқылы бір-біріне қоңырау шалу мүмкіндігі болды. Неғұрлым дұрыс сервиске, ал болашақта микросервис архитектурасына көшудің нақты алғышарттары болды.

Біз декомпозиция бойынша жұмысымызды 2015 жылы бастадық. Біз әлі идеалды күйге жеткен жоқпыз – үлкен жобаның монолит деп атауға болмайтын бөліктері әлі де бар, бірақ олар да микросервистерге ұқсамайды. Соған қарамастан, ілгерілеушілік айтарлықтай.
Мен бұл туралы мақалада айтатын боламын.

Монолиттен микросервиске көшу: тарих және тәжірибе

Мазмұны

Архитектура және бар шешімнің мәселелері


Бастапқыда архитектурасы келесідей болды: UI - бұл жеке қосымша, монолитті бөлігі Visual Basic 6-да жазылған, .NET қосымшасы - жеткілікті үлкен деректер қорымен жұмыс істейтін байланысты қызметтер жиынтығы.

Алдыңғы шешімнің кемшіліктері

Бір сәтсіздік нүктесі
Бізде бір ғана сәтсіздік болды: .NET қолданбасы бір процесте жұмыс істеді. Кез келген модуль сәтсіз болса, бүкіл қолданба сәтсіз аяқталды және оны қайта іске қосу керек болды. Біз әртүрлі пайдаланушылар үшін көптеген процестерді автоматтандыратындықтан, олардың біріндегі сәтсіздікке байланысты барлығы біраз уақыт жұмыс істей алмады. Ал бағдарламалық құрал қатесі болған жағдайда, тіпті сақтық көшірме де көмектеспеді.

Жақсартулар кезегі
Бұл кемшілік біршама ұйымдастырушылық. Біздің қолданбамызда көптеген тұтынушылар бар және олардың барлығы оны мүмкіндігінше тезірек жақсартқысы келеді. Бұрын мұны параллель орындау мүмкін емес еді, барлық тұтынушылар кезекте тұрған. Бұл процесс бизнес үшін жағымсыз болды, өйткені олар өз міндеттерінің құнды екенін дәлелдеуге мәжбүр болды. Ал әзірлеу тобы бұл кезекті ұйымдастыруға уақыт жұмсады. Бұл көп уақыт пен күш-жігерді қажет етті, сайып келгенде, өнім олар қалағандай тез өзгере алмады.

Ресурстарды оңтайлы емес пайдалану
Қызметтерді бір процесте орналастыру кезінде біз әрқашан конфигурацияны серверден серверге толығымен көшіреміз. Біз ресурстарды ысырап етпеу және орналастыру схемасын икемді басқаруды алу үшін ең ауыр жүктелген қызметтерді бөлек орналастырғымыз келді.

Заманауи технологияларды енгізу қиын
Барлық әзірлеушілерге таныс мәселе: жобаға заманауи технологияларды енгізу ниеті бар, бірақ мүмкіндік жоқ. Үлкен монолитті шешіммен ағымдағы кітапхананың кез келген жаңартуы, жаңасына көшуді айтпағанда, өте маңызды емес міндетке айналады. Команда басшысына бұл босқа нервтерден гөрі көбірек бонус әкелетінін дәлелдеу үшін көп уақыт қажет.

Өзгерістерді шығарудың қиындығы
Бұл ең маңызды мәселе болды - біз екі ай сайын шығарылымдарды шығардық.
Әрбір шығарылым әзірлеушілердің сынақтары мен күш-жігеріне қарамастан, банк үшін нағыз апатқа айналды. Бизнес аптаның басында оның кейбір функциялары жұмыс істемейтінін түсінді. Ал әзірлеушілер оларды бір апта ауыр оқиғалар күтіп тұрғанын түсінді.
Барлығында жағдайды өзгерту ниеті болды.

Микросервистерден күту


Дайын болған кезде компоненттерді беру. Ерітіндіні ыдырату және әртүрлі процестерді бөлу арқылы дайын болған кезде компоненттерді жеткізу.

Шағын өнім топтары. Бұл өте маңызды, өйткені ескі монолитте жұмыс істейтін үлкен топты басқару қиын болды. Мұндай команда қатаң процесс бойынша жұмыс істеуге мәжбүр болды, бірақ олар шығармашылық пен тәуелсіздікті қалайды. Мұны тек шағын командалар ғана көтере алады.

Бөлек процестерде қызметтерді оқшаулау. Ең дұрысы, мен оны контейнерлерде оқшаулауды қаладым, бірақ .NET Framework жүйесінде жазылған көптеген қызметтер тек Windows жүйесінде жұмыс істейді. .NET Core негізіндегі қызметтер қазір пайда болуда, бірақ олардың саны әлі аз.

Орналастыру икемділігі. Біз қызметтерді кодтың мәжбүрлеу тәсілін емес, бізге қажет етіп біріктіргіміз келеді.

Жаңа технологияларды қолдану. Бұл кез келген бағдарламашы үшін қызықты.

Өтпелі проблемалар


Әрине, егер монолитті микросервистерге бөлу оңай болса, бұл туралы конференцияларда айтып, мақалалар жазудың қажеті болмас еді. Бұл процесте көптеген тұзақтар бар, мен бізге кедергі келтірген негізгілерін сипаттаймын.

Бірінші мәселе монолиттердің көпшілігіне тән: іскерлік логиканың үйлесімділігі. Монолитті жазғанда, қажетсіз кодты жазбау үшін сыныптарымызды қайта пайдаланғымыз келеді. Ал микросервистерге көшкен кезде бұл проблемаға айналады: барлық код өте тығыз байланысқан және қызметтерді бөлу қиын.

Жұмыс басталған кезде репозиторийде 500-ден астам жоба және 700 мыңнан астам код жолдары болды. Бұл өте үлкен шешім және екінші мәселе. Оны жай ғана алып, микросервистерге бөлу мүмкін болмады.

Үшінші мәселе — қажетті инфрақұрылымның болмауы. Шын мәнінде, біз серверлерге бастапқы кодты қолмен көшірдік.

Монолиттен микросервистерге қалай өтуге болады


Микросервистерді қамтамасыз ету

Біріншіден, біз микросервистерді бөлу итерациялық процесс екенін бірден анықтадық. Бізден әрқашан бизнес мәселелерін қатар дамыту талап етілді. Мұны техникалық тұрғыдан қалай жүзеге асыратынымыз қазірдің өзінде біздің мәселеміз. Сондықтан біз итерациялық процеске дайындалдық. Егер сізде үлкен қолданба болса және ол бастапқыда қайта жазуға дайын болмаса, ол басқа жолмен жұмыс істемейді.

Микросервистерді оқшаулау үшін қандай әдістерді қолданамыз?

Бірінші әдіс — бар модульдерді қызметтер ретінде жылжыту. Осыған байланысты, бізде сәттілік болды: WCF хаттамасы арқылы жұмыс істейтін тіркелген қызметтер болды. Олар бөлек ассамблеяларға бөлінді. Біз оларды бөлек тасымалдадық, әрбір құрылымға шағын іске қосу құралын қостық. Ол қосымшаны қызмет ретінде де, консоль ретінде де іске қосуға мүмкіндік беретін тамаша Topshelf кітапханасының көмегімен жазылған. Бұл түзету үшін ыңғайлы, себебі шешімде қосымша жобалар қажет емес.

Қызметтер іскерлік логикаға сәйкес қосылды, өйткені олар жалпы жинақтарды пайдаланды және ортақ дерекқормен жұмыс істеді. Оларды таза түрде микросервис деп атауға болмайды. Дегенмен, біз бұл қызметтерді әртүрлі процестерде бөлек ұсына аламыз. Осының өзі олардың бір-біріне ықпалын азайтуға мүмкіндік берді, параллельді дамумен және бір сәтсіздікпен проблеманы азайтты.

Хостпен құрастыру Бағдарлама класындағы кодтың бір жолы ғана. Біз Топшелфпен жұмысты көмекші сыныпта жасырдық.

namespace RBA.Services.Accounts.Host
{
   internal class Program
   {
      private static void Main(string[] args)
      {
        HostRunner<Accounts>.Run("RBA.Services.Accounts.Host");

       }
    }
}

Микросервистерді бөлудің екінші жолы: жаңа мәселелерді шешу үшін оларды құру. Егер бір уақытта монолит өспесе, бұл өте жақсы, яғни біз дұрыс бағытта қозғаламыз. Жаңа мәселелерді шешу үшін біз бөлек қызметтерді құруға тырыстық. Егер мұндай мүмкіндік болса, біз жеке деректер моделін, жеке дерекқорды толығымен басқаратын көбірек «канондық» қызметтерді жасадық.

Біз, көптеген адамдар сияқты, аутентификация және авторизация қызметтерінен бастадық. Олар бұл үшін тамаша. Олар тәуелсіз, әдетте, оларда жеке деректер үлгісі бар. Олардың өздері монолитпен араласпайды, тек кейбір мәселелерді шешу үшін оларға жүгінеді. Осы қызметтерді пайдалана отырып, сіз жаңа архитектураға көшуді бастай аласыз, олардағы инфрақұрылымды жөндеуге, желілік кітапханаларға қатысты кейбір тәсілдерді қолдануға және т.б. Ұйымымызда аутентификация қызметін жасай алмайтын командалар жоқ.

Микросервистерді бөлудің үшінші жолыБіз қолданатын нәрсе бізге біршама тән. Бұл UI деңгейінен бизнес логикасын жою. Біздің негізгі UI қосымшамыз жұмыс үстелі болып табылады; ол сервер сияқты C# тілінде жазылған. Әзірлеушілер мезгіл-мезгіл қателіктер жіберді және логиканың серверде болуы және қайта пайдаланылуы керек бөліктерін UI-ге тасымалдады.

UI бөлігінің кодынан нақты мысалды қарасаңыз, бұл шешімнің көпшілігінде тек UI пішінін құру үшін емес, басқа процестерде пайдалы нақты бизнес логикасы бар екенін көре аласыз.

Монолиттен микросервиске көшу: тарих және тәжірибе

Нағыз UI логикасы соңғы екі жолда ғана бар. Біз оны серверге қайта пайдалануға болатындай етіп жібердік, осылайша пайдаланушы интерфейсін азайтып, дұрыс архитектураға қол жеткіздік.

Микросервистерді оқшаулаудың төртінші және ең маңызды жолы, бұл монолитті азайтуға мүмкіндік береді, өңдеумен бар қызметтерді жою болып табылады. Қолданыстағы модульдерді сол қалпында алып тастаған кезде нәтиже әрқашан әзірлеушілерге ұнай бермейді және функционалдылық жасалғаннан бері бизнес-процесс ескірген болуы мүмкін. Рефакторинг арқылы біз жаңа бизнес-процеске қолдау көрсете аламыз, өйткені бизнес талаптары үнемі өзгеріп отырады. Біз бастапқы кодты жақсарта аламыз, белгілі ақауларды жоя аламыз және жақсырақ деректер үлгісін жасай аламыз. Пайдасы көп.

Қызметтерді өңдеуден бөлу шектелген контекст түсінігімен ажырамас байланысты. Бұл Domain Driven Design концепциясы. Бұл бір тілдің барлық терминдері бірегей түрде анықталған домендік модель бөлімін білдіреді. Мысал ретінде сақтандыру мен шоттардың контекстін қарастырайық. Бізде монолитті қосымша бар және біз сақтандырудағы шотпен жұмыс істеуіміз керек. Әзірлеуші ​​басқа жинақта бар Тіркелгі сыныбын тауып, оған сақтандыру сыныбынан сілтеме жасайды деп күтеміз және бізде жұмыс коды болады. DRY принципі сақталады, тапсырма бар кодты пайдалану арқылы жылдамырақ орындалады.

Нәтижесінде шоттар мен сақтандыру контексттері байланысты болып шықты. Жаңа талаптардың пайда болуына қарай, бұл байланыс онсыз да күрделі бизнес логикасының күрделілігін арттыра отырып, дамуға кедергі жасайды. Бұл мәселені шешу үшін кодтағы контекстер арасындағы шекараларды тауып, олардың бұзушылықтарын жою керек. Мысалы, сақтандыру контекстінде Орталық банктің 20 таңбалы шот нөмірі мен шот ашылған күні жеткілікті болуы әбден мүмкін.

Осы шектелген мәтінмәндерді бір-бірінен бөлу және микросервистерді монолитті шешімнен бөлу процесін бастау үшін қолданба ішінде сыртқы API интерфейстерін жасау сияқты тәсілді қолдандық. Егер біз қандай да бір модуль микросервиске айналуы керек екенін білсек, процесте қандай да бір түрде өзгертілген болса, онда біз сыртқы қоңыраулар арқылы басқа шектеулі контекстке жататын логикаға дереу қоңырау шалдық. Мысалы, REST немесе WCF арқылы.

Біз таратылған транзакцияларды қажет ететін кодтан аулақ болмайтынымызды шештік. Біздің жағдайда бұл ережені сақтау оңай болды. Біз қатаң бөлінген транзакциялар шынымен қажет болатын жағдайларды әлі кездестірген жоқпыз - модульдер арасындағы соңғы сәйкестік жеткілікті.

Нақты мысалды қарастырайық. Бізде оркестр ұғымы бар - «қолданбаның» нысанын өңдейтін құбыр. Ол кезекпен клиент, шот және банк картасын жасайды. Клиент пен тіркелгі сәтті жасалған болса, бірақ картаны жасау сәтсіз аяқталса, қолданба «сәтті» күйіне ауыспайды және «карта жасалмаған» күйінде қалады. Болашақта фондық әрекет оны алып, аяқтайды. Жүйе біраз уақыттан бері сәйкессіздік жағдайында болды, бірақ біз бұған жалпы қанағаттанамыз.

Егер деректердің бір бөлігін дәйекті түрде сақтау қажет болғанда жағдай туындаса, біз оны бір процесте өңдеу үшін қызметті біріктіруге барамыз.

Микросервисті бөлу мысалын қарастырайық. Оны өндіріске салыстырмалы түрде қауіпсіз түрде қалай жеткізуге болады? Бұл мысалда бізде жүйенің жеке бөлігі бар - жалақы төлеуге қызмет көрсету модулі, оның код бөлімдерінің бірі микросервис жасағымыз келеді.

Монолиттен микросервиске көшу: тарих және тәжірибе

Ең алдымен кодты қайта жазу арқылы микросервис жасаймыз. Біз көңілімізден шықпаған кейбір аспектілерді жетілдіреміз. Біз тұтынушыдан жаңа бизнес талаптарын енгіземіз. Біз интерфейс пен сервер арасындағы байланысқа API шлюзін қосамыз, ол қоңырауды қайта бағыттауды қамтамасыз етеді.

Монолиттен микросервиске көшу: тарих және тәжірибе

Содан кейін біз бұл конфигурацияны іске қосамыз, бірақ пилоттық күйде. Пайдаланушыларымыздың көпшілігі бұрынғыша ескі бизнес-процестермен жұмыс істейді. Жаңа пайдаланушылар үшін біз бұдан былай бұл процесті қамтымайтын монолитті қолданбаның жаңа нұсқасын жасап жатырмыз. Негізінде, бізде пилот ретінде жұмыс істейтін монолит пен микросервистің үйлесімі бар.

Монолиттен микросервиске көшу: тарих және тәжірибе

Сәтті ұшқышпен біз жаңа конфигурацияның шынымен жұмыс істейтінін түсінеміз, біз теңдеуден ескі монолитті алып тастап, ескі шешімнің орнына жаңа конфигурацияны қалдыра аламыз.

Монолиттен микросервиске көшу: тарих және тәжірибе

Жалпы алғанда, біз монолиттің бастапқы кодын бөлудің барлық дерлік әдістерін қолданамыз. Олардың барлығы қосымшаның бөліктерінің өлшемін азайтуға және оларды жаңа кітапханаларға аударуға, бастапқы кодты жақсартуға мүмкіндік береді.

Мәліметтер қорымен жұмыс


Деректер қорын бастапқы кодқа қарағанда нашар бөлуге болады, өйткені ол тек ағымдағы схеманы ғана емес, сонымен бірге жинақталған тарихи деректерді де қамтиды.

Біздің деректер базасының, басқалар сияқты, тағы бір маңызды кемшілігі болды - оның үлкен көлемі. Бұл дерекқор монолиттің күрделі іскерлік логикасына және әртүрлі шектелген контексттердің кестелері арасында жинақталған қатынастарға сәйкес жасалған.

Біздің жағдайда, барлық қиындықтарды (үлкен дерекқор, көптеген қосылымдар, кестелер арасындағы кейде анық емес шекаралар) шешу үшін көптеген ірі жобаларда кездесетін мәселе туындады: ортақ дерекқор үлгісін пайдалану. Деректер кестелерден көрініс, репликация арқылы алынды және осы репликация қажет болған басқа жүйелерге жіберілді. Нәтижесінде біз кестелерді бөлек схемаға жылжыта алмадық, өйткені олар белсенді қолданылған.

Кодтағы шектеулі контексттерге бірдей бөлу бізге бөлуге көмектеседі. Бұл әдетте дерекқор деңгейінде деректерді қалай бөлшектейтініміз туралы жақсы түсінік береді. Біз қандай кестелер бір шектелген контекстке, қайсысы екіншісіне жататынын түсінеміз.

Біз дерекқорды бөлудің екі ғаламдық әдісін қолдандық: бар кестелерді бөлу және өңдеу арқылы бөлу.

Қолданыстағы кестелерді бөлу деректер құрылымы жақсы болса, бизнес талаптарына сай болса және барлығы оған риза болса, пайдаланудың жақсы әдісі болып табылады. Бұл жағдайда біз бар кестелерді бөлек схемаға бөле аламыз.

Өңдейтін бөлім бизнес-модель қатты өзгерген кезде қажет, ал кестелер бізді мүлде қанағаттандырмайды.

Бар кестелерді бөлу. Біз нені бөлетінімізді анықтауымыз керек. Бұл білімсіз ештеңе жұмыс істемейді және мұнда кодтағы шектелген контексттерді бөлу бізге көмектеседі. Әдетте, егер сіз бастапқы кодтағы мәтінмәндердің шекараларын түсіне алсаңыз, бөлім үшін тізімге қандай кестелерді енгізу керек екені белгілі болады.

Бізде екі монолитті модуль бір дерекқормен өзара әрекеттесетін шешім бар деп елестетіп көрейік. Бөлінген кестелер бөлімімен тек бір модуль әрекеттесетініне, ал екіншісі API арқылы онымен әрекеттесе бастайтынына көз жеткізуіміз керек. Бастау үшін API арқылы тек жазу жүргізілсе жеткілікті. Бұл микросервистердің тәуелсіздігі туралы айту үшін қажетті шарт. Оқу қосылымдары үлкен мәселе болмағанша сақталуы мүмкін.

Монолиттен микросервиске көшу: тарих және тәжірибе

Келесі қадам - ​​біз өңдеумен немесе өңдеусіз бөлінген кестелермен жұмыс істейтін код бөлімін бөлек микросервиске бөліп, оны бөлек процесте, контейнерде іске қоса аламыз. Бұл монолитті дерекқорға және оған тікелей қатысы жоқ кестелерге қосылатын бөлек қызмет болады. Монолит әлі де ажыратылатын бөлікпен оқу үшін өзара әрекеттеседі.

Монолиттен микросервиске көшу: тарих және тәжірибе

Кейінірек біз бұл қосылымды жоямыз, яғни бөлінген кестелерден монолитті қолданбадан оқу деректері де API-ге тасымалданады.

Монолиттен микросервиске көшу: тарих және тәжірибе

Әрі қарай, біз жалпы дерекқордан тек жаңа микросервис жұмыс істейтін кестелерді таңдаймыз. Біз кестелерді бөлек схемаға немесе тіпті жеке физикалық дерекқорға жылжыта аламыз. Микросервис пен монолитті дерекқор арасында әлі де оқу байланысы бар, бірақ алаңдайтын ештеңе жоқ, бұл конфигурацияда ол өте ұзақ уақыт өмір сүре алады.

Монолиттен микросервиске көшу: тарих және тәжірибе

Соңғы қадам - ​​барлық қосылымдарды толығымен жою. Бұл жағдайда бізге деректерді негізгі дерекқордан тасымалдау қажет болуы мүмкін. Кейде біз сыртқы жүйелерден қайталанған кейбір деректерді немесе каталогтарды бірнеше дерекқорларда қайта пайдаланғымыз келеді. Бұл бізде мезгіл-мезгіл болып тұрады.

Монолиттен микросервиске көшу: тарих және тәжірибе

Өңдеу бөлімі. Бұл әдіс біріншіге өте ұқсас, тек кері тәртіпте. Біз жаңа дерекқорды және API арқылы монолитпен әрекеттесетін жаңа микросервисті дереу бөлеміз. Бірақ сонымен бірге біз болашақта жойғымыз келетін деректер қоры кестелерінің жиынтығы қалады. Ол бізге енді қажет емес, біз оны жаңа үлгіде ауыстырдық.

Монолиттен микросервиске көшу: тарих және тәжірибе

Бұл схема жұмыс істеуі үшін бізге өтпелі кезең қажет болуы мүмкін.

Сонда екі ықтимал тәсіл бар.

бірінші: біз жаңа және ескі дерекқорлардағы барлық деректерді көшіреміз. Бұл жағдайда бізде деректердің артық болуы және синхрондау мәселелері туындауы мүмкін. Бірақ біз екі түрлі клиентті қабылдай аламыз. Біреуі жаңа нұсқамен, екіншісі ескі нұсқамен жұмыс істейді.

секунд: біз деректерді кейбір бизнес критерийлері бойынша бөлеміз. Мысалы, бізде ескі дерекқорда сақталған жүйеде 5 өнім болды. Алтыншысын біз жаңа дерекқорға жаңа бизнес тапсырмасы аясында орналастырамыз. Бірақ бізге осы деректерді синхрондайтын және клиентке қайдан және не алу керектігін көрсететін API шлюзі қажет болады.

Екі тәсіл де жұмыс істейді, жағдайға байланысты таңдаңыз.

Барлығы жұмыс істеп тұрғанына сенімді болғаннан кейін, ескі дерекқор құрылымдарымен жұмыс істейтін монолит бөлігін өшіруге болады.

Монолиттен микросервиске көшу: тарих және тәжірибе

Соңғы қадам ескі деректер құрылымдарын жою болып табылады.

Монолиттен микросервиске көшу: тарих және тәжірибе

Қорытындылай келе, бізде деректер қорымен проблемалар бар деп айта аламыз: бастапқы кодпен салыстырғанда онымен жұмыс істеу қиын, оны бөлісу қиынырақ, бірақ оны жасауға болады және істеу керек. Біз мұны қауіпсіз орындауға мүмкіндік беретін кейбір жолдарды таптық, бірақ бастапқы кодқа қарағанда деректермен қателесу оңайырақ.

Бастапқы кодпен жұмыс


Монолитті жобаны талдауды бастаған кезде бастапқы код диаграммасы осылай болды.

Монолиттен микросервиске көшу: тарих және тәжірибе

Оны шамамен үш қабатқа бөлуге болады. Бұл іске қосылған модульдер, плагиндер, қызметтер және жеке әрекеттер қабаты. Шын мәнінде, бұл монолитті шешімдегі кіру нүктелері болды. Олардың барлығы Жалпы қабатпен тығыз жабылған. Бұл қызметтер ортақ іскерлік логикаға және көптеген байланыстарға ие болды. Әрбір қызмет пен плагин көлеміне және әзірлеушілердің санасына байланысты 10 немесе одан да көп жалпы жинақтарды пайдаланды.

Бізде бөлек пайдалануға болатын инфрақұрылымдық кітапханалар болғаны бақытқа кенелді.

Кейде кейбір жалпы нысандар шын мәнінде бұл қабатқа жатпайтын, бірақ инфрақұрылымдық кітапхана болған жағдай туындады. Бұл атауды өзгерту арқылы шешілді.

Ең үлкен алаңдаушылық шектеулі контексттер болды. Бір Жалпы жиналыста 3-4 контекст араласып, бір іскерлік функциялар аясында бір-бірін пайдаланатын болды. Оны қай жерде және қандай шекаралар бойынша бөлуге болатынын және бұл бөлімді бастапқы код жиындарына салыстыру арқылы әрі қарай не істеу керектігін түсіну қажет болды.

Біз кодты бөлу процесі үшін бірнеше ережелерді тұжырымдадық.

Бірінші: Біз енді қызметтер, әрекеттер және плагиндер арасында бизнес логикасын бөліскіміз келмеді. Біз бизнес логикасын микросервистердің ішінде тәуелсіз еткіміз келді. Микросервистер, керісінше, толығымен тәуелсіз қызмет ететін қызметтер ретінде қарастырылады. Менің ойымша, бұл тәсіл біршама ысырапшыл және оған жету қиын, өйткені, мысалы, C# тіліндегі қызметтер кез келген жағдайда стандартты кітапхана арқылы қосылады. Біздің жүйе C# тілінде жазылған, біз басқа технологияларды әлі пайдаланған жоқпыз. Сондықтан біз ортақ техникалық жинақтарды пайдалануға мүмкіндік аламыз деп шештік. Ең бастысы, оларда бизнес логикасының фрагменттері жоқ. Егер сізде пайдаланып жатқан ORM үстіне ыңғайлы орауыш болса, оны қызметтен қызметке көшіру өте қымбатқа түседі.

Біздің команда доменге негізделген дизайнның жанкүйері, сондықтан пияз архитектурасы біз үшін өте қолайлы болды. Біздің қызметтеріміздің негізі деректерге қол жеткізу деңгейі емес, тек бизнес логикасын қамтитын және инфрақұрылыммен байланысы жоқ домен логикасы бар жинақ болып табылады. Сонымен қатар, біз фреймворктерге қатысты мәселелерді шешу үшін домен жинағын дербес өзгерте аламыз.

Осы кезеңде біз бірінші күрделі мәселемізге тап болдық. Қызмет бір домен жинағына сілтеме жасауы керек еді, біз логиканы тәуелсіз еткіміз келді, ал DRY принципі мұнда бізге қатты кедергі келтірді. Әзірлеушілер қайталануды болдырмау үшін көрші жинақтардағы сыныптарды қайта пайдаланғысы келді, нәтижесінде домендер қайтадан бір-бірімен байланыстыра бастады. Біз нәтижелерді талдадық және мәселе бастапқы кодты сақтау құрылғысының аймағында болуы мүмкін деп шештік. Бізде барлық бастапқы кодты қамтитын үлкен репозиторий болды. Бүкіл жобаның шешімін жергілікті машинада жинау өте қиын болды. Сондықтан, жобаның бөліктері үшін жеке шағын шешімдер жасалды және ешкім оларға кейбір жалпы немесе домен жиынын қосуға және оларды қайта пайдалануға тыйым салған жоқ. Мұны істеуге мүмкіндік бермейтін жалғыз құрал - кодты қарау. Бірақ кейде бұл да сәтсіз болды.

Содан кейін біз бөлек репозиторийлері бар үлгіге көшуді бастадық. Бизнес логикасы енді қызметтен қызметке ауыспайды, домендер шынымен тәуелсіз болды. Шектелген контексттерге нақтырақ қолдау көрсетіледі. Инфрақұрылымдық кітапханаларды қалай қайта пайдаланамыз? Біз оларды бөлек репозиторийге бөлдік, содан кейін оларды Nuget бумаларына орналастырдық, біз оларды Artifactory-ге орналастырдық. Кез келген өзгертулермен жинақтау және жариялау автоматты түрде орын алады.

Монолиттен микросервиске көшу: тарих және тәжірибе

Біздің қызметтеріміз сыртқы инфрақұрылымдар сияқты ішкі инфрақұрылым пакеттеріне сілтеме жасай бастады. Біз Nuget-тен сыртқы кітапханаларды жүктеп аламыз. Artifactory-мен жұмыс істеу үшін, біз осы пакеттерді орналастырдық, біз екі пакет менеджерін қолдандық. Шағын репозиторийлерде біз Nuget-ті де қолдандық. Бірнеше қызметтері бар репозиторийлерде біз модульдер арасында көбірек нұсқа сәйкестігін қамтамасыз ететін пакетті қолдандық.

Монолиттен микросервиске көшу: тарих және тәжірибе

Осылайша, бастапқы кодпен жұмыс істеу, архитектураны сәл өзгерту және репозиторийлерді бөлу арқылы біз қызметтерімізді тәуелсіз етеміз.

Инфрақұрылымдық проблемалар


Микросервистерге көшудің көптеген кемшіліктері инфрақұрылыммен байланысты. Сізге автоматтандырылған орналастыру қажет, инфрақұрылымды іске қосу үшін жаңа кітапханалар қажет.

Орталарда қолмен орнату

Бастапқыда біз орталарға арналған шешімді қолмен орнаттық. Бұл процесті автоматтандыру үшін біз CI/CD құбырын жасадық. Біз үздіксіз жеткізу процесін таңдадық, өйткені үздіксіз енгізу бизнес-процестері тұрғысынан біз үшін әлі қолайлы емес. Сондықтан операцияға жіберу түйменің көмегімен, ал тестілеу үшін автоматты түрде жүзеге асырылады.

Монолиттен микросервиске көшу: тарих және тәжірибе

Біз бастапқы кодты сақтау үшін Atlassian, Bitbucket және құрылыс үшін Bamboo қолданамыз. Біз Cake-те құрастыру сценарийлерін жазғанды ​​ұнатамыз, себебі ол C#-мен бірдей. Дайын пакеттер Artifactory-ге келеді, ал Ansible автоматты түрде сынақ серверлеріне түседі, содан кейін оларды дереу тексеруге болады.

Монолиттен микросервиске көшу: тарих және тәжірибе

Бөлек тіркеу


Бір кездері монолит идеяларының бірі ортақ ағаш кесуді қамтамасыз ету болды. Біз сондай-ақ дискілердегі жеке журналдармен не істеу керектігін түсінуіміз керек еді. Біздің журналдар мәтіндік файлдарға жазылады. Біз стандартты ELK стекін пайдалануды шештік. Біз ELK-ке провайдерлер арқылы тікелей хат жазбадық, бірақ бұл журналдарды кейінірек талдауға болатындай етіп, қызмет атауын қосып, мәтіндік журналдарды өзгертіп, оларға бақылау идентификаторын идентификатор ретінде жазамыз деп шештік.

Монолиттен микросервиске көшу: тарих және тәжірибе

Filebeat көмегімен біз журналдарымызды серверлерден жинауға, содан кейін оларды түрлендіруге, UI-де сұрауларды құру үшін Kibana қолданбасын пайдалануға және қызметтер арасында қоңыраудың қалай өткенін көруге мүмкіндік аламыз. Trace ID бұған көп көмектеседі.

Қатысты қызметтерді тестілеу және жөндеу


Бастапқыда біз әзірленіп жатқан қызметтерді қалай түзетуге болатынын толық түсінбедік. Монолитпен бәрі қарапайым болды, біз оны жергілікті машинада іске қостық. Бастапқыда олар микросервистермен де солай істеуге тырысты, бірақ кейде бір микросервисті толық іске қосу үшін бірнеше басқасын іске қосу қажет, бұл ыңғайсыз. Біз жергілікті құрылғыда жөндеуді қалайтын қызметті немесе қызметтерді ғана қалдыратын үлгіге көшу керек екенін түсіндік. Қалған қызметтер конфигурацияға өніммен сәйкес келетін серверлерден пайдаланылады. Түзетуден кейін тестілеу кезінде әрбір тапсырма үшін тек өзгертілген қызметтер сынақ серверіне шығарылады. Осылайша, ерітінді болашақта өндірісте пайда болатын пішінде сыналады.

Қызметтердің өндірістік нұсқаларын ғана іске қосатын серверлер бар. Бұл серверлер оқиғалар болған жағдайда, орналастыру алдында жеткізуді тексеру және ішкі оқыту үшін қажет.

Біз танымал Specflow кітапханасының көмегімен автоматтандырылған тестілеу процесін қостық. Сынақтар Ansible қолданбасынан орналастырудан кейін бірден NUnit көмегімен автоматты түрде іске қосылады. Егер тапсырманы қамту толығымен автоматты болса, онда қолмен тестілеудің қажеті жоқ. Кейде қосымша қолмен тестілеу қажет болса да. Белгілі бір мәселе бойынша қандай сынақтарды орындау керектігін анықтау үшін Jira жүйесінде тегтерді қолданамыз.

Бұған қоса, жүктемені сынау қажеттілігі артты, бұрын ол сирек жағдайларда ғана жүргізілетін. Біз сынақтарды орындау үшін JMeter, оларды сақтау үшін InfluxDB және процесс графиктерін құру үшін Grafana пайдаланамыз.

Біз неге қол жеткіздік?


Біріншіден, біз «шығару» ұғымынан құтылдық. Бұл колосс өндіріс ортасына орналастырылып, бизнес-процестерді уақытша бұзған екі айлық сұмдық шығарылымдар өтті. Қазір біз қызметтерді орта есеппен 1,5 күн сайын орналастырып, оларды топтастырудамыз, өйткені олар бекітілгеннен кейін іске қосылады.

Біздің жүйеде өлімге әкелетін ақаулар жоқ. Егер біз қатесі бар микросервисті шығарсақ, онда онымен байланысты функционалдық бұзылады және басқа барлық функцияларға әсер етпейді. Бұл пайдаланушы тәжірибесін айтарлықтай жақсартады.

Біз орналастыру үлгісін басқара аламыз. Қажет болса, қызметтердің топтарын шешімнің қалған бөлігінен бөлек таңдауға болады.

Сонымен қатар, біз жақсартулардың үлкен кезегімен проблеманы айтарлықтай азайттық. Қазір бізде кейбір қызметтермен дербес жұмыс істейтін бөлек өнім топтары бар. Scrum процесі қазірдің өзінде бұл жерде жақсы сәйкес келеді. Белгілі бір топта оған тапсырмалар тағайындайтын бөлек өнім иесі болуы мүмкін.

Резюме

  • Микросервис күрделі жүйелерді ыдырату үшін өте қолайлы. Бұл процесте біз жүйемізде не бар, қандай шектеулі контексттер бар, олардың шекаралары қайда жатқанын түсіне бастаймыз. Бұл жақсартуларды модульдер арасында дұрыс бөлуге және кодтың шатасуын болдырмауға мүмкіндік береді.
  • Микросервистер ұйымдық артықшылықтар береді. Олар көбінесе сәулет ретінде ғана айтылады, бірақ кез келген архитектура өз бетінше емес, бизнес қажеттіліктерін шешу үшін қажет. Сондықтан, Scrum қазір өте танымал екенін ескере отырып, микросервистер шағын командалардағы мәселелерді шешуге өте қолайлы деп айта аламыз.
  • Бөлу - қайталанатын процесс. Сіз қолданбаны алып, оны микросервистерге бөлуге болмайды. Алынған өнімнің жұмыс істеуі екіталай. Микросервистерді арнаған кезде, бар мұраны қайта жазу пайдалы, яғни оны бізге ұнайтын және функционалдылық пен жылдамдық тұрғысынан бизнес қажеттіліктерін жақсырақ қанағаттандыратын кодқа айналдыру.

    Шағын ескерту: Микросервистерге көшу шығындары өте маңызды. Инфрақұрылым мәселесін жалғыз шешуге көп уақыт кетті. Сондықтан, егер сізде нақты масштабтауды қажет етпейтін шағын қолданба болса, сіздің командаңыздың назары мен уақыты үшін бәсекелесетін тұтынушылардың көп саны болмаса, микросервистер бүгінгі күні сізге қажет нәрсе болмауы мүмкін. Бұл өте қымбат. Процесті микросервистерден бастасаңыз, бастапқыда монолит әзірлеумен бір жобаны бастағанға қарағанда шығындар жоғары болады.

    PS Неғұрлым эмоционалды оқиға (және жеке сізге арналған сияқты) - сәйкес байланыс.
    Міне, есептің толық нұсқасы.

Ақпарат көзі: www.habr.com

пікір қалдыру