Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Šajā rakstā es runāŔu par to, kā projekts, pie kura es strādāju, no liela monolīta tika pārveidots par mikropakalpojumu komplektu.

Projekts savu vēsturi sāka diezgan sen, 2000. gada sākumā. Pirmās versijas tika rakstÄ«tas Visual Basic 6. Laika gaitā kļuva skaidrs, ka attÄ«stÄ«ba Å”ajā valodā nākotnē bÅ«s grÅ«ti atbalstāma, jo IDE un pati valoda ir vāji attÄ«stÄ«ta. 2000. gadu beigās tika nolemts pāriet uz daudzsoloŔāko C#. Jaunā versija tika rakstÄ«ta paralēli vecās versijas pārskatÄ«Å”anai, pakāpeniski arvien vairāk kodu tika ierakstÄ«ts .NET. C# aizmugure sākotnēji bija vērsta uz pakalpojumu arhitektÅ«ru, taču izstrādes laikā tika izmantotas kopÄ«gas bibliotēkas ar loÄ£iku un pakalpojumi tika palaisti vienā procesā. Rezultāts bija lietojumprogramma, ko mēs saucām par "pakalpojuma monolÄ«tu".

Viena no nedaudzajām Ŕīs kombinācijas priekÅ”rocÄ«bām bija pakalpojumu iespēja zvanÄ«t viens otram, izmantojot ārēju API. Bija skaidri priekÅ”noteikumi pārejai uz pareizāku servisu un nākotnē mikropakalpojumu arhitektÅ«ru.

Mēs sākām darbu pie dekompozÄ«cijas ap 2015. gadu. Mēs vēl neesam sasnieguÅ”i ideālu stāvokli - joprojām ir liela projekta daļas, kuras diez vai var saukt par monolÄ«tiem, taču tās arÄ« neizskatās pēc mikropakalpojumiem. Tomēr progress ir ievērojams.
Par to es runāŔu rakstā.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

saturs

EsoŔā risinājuma arhitektÅ«ra un problēmas


Sākotnēji arhitektÅ«ra izskatÄ«jās Ŕādi: UI ir atseviŔķa lietojumprogramma, monolÄ«tā daļa ir rakstÄ«ta Visual Basic 6, .NET lietojumprogramma ir saistÄ«tu pakalpojumu kopums, kas strādā ar diezgan lielu datu bāzi.

IepriekŔējā risinājuma trÅ«kumi

Viens neveiksmes punkts
Mums bija viens neveiksmes punkts: .NET lietojumprogramma darbojās vienā procesā. Ja kāds modulis neizdevās, visa lietojumprogramma neizdevās, un tā bija jārestartē. Tā kā mēs automatizējam lielu skaitu procesu dažādiem lietotājiem, kļūmes dēļ vienā no tiem visi kādu laiku nevarēja strādāt. Un programmatÅ«ras kļūdas gadÄ«jumā pat dublÄ“Å”ana nepalÄ«dzēja.

Uzlabojumu rinda
Å is trÅ«kums ir diezgan organizatorisks. MÅ«su lietojumprogrammai ir daudz klientu, un viņi visi vēlas to uzlabot pēc iespējas ātrāk. IepriekÅ” to nebija iespējams izdarÄ«t paralēli, un visi klienti stāvēja rindā. Å is process uzņēmējiem bija negatÄ«vs, jo viņiem bija jāpierāda, ka viņu uzdevums ir vērtÄ«gs. Un izstrādes komanda pavadÄ«ja laiku, organizējot Å”o rindu. Tas prasÄ«ja daudz laika un pūļu, un galu galā produkts nevarēja mainÄ«ties tik ātri, kā viņi bÅ«tu vēlējuÅ”ies.

Neoptimāla resursu izmantoŔana
Mitinot pakalpojumus vienā procesā, mēs vienmēr pilnÄ«bā kopējām konfigurāciju no servera uz serveri. Mēs vēlējāmies visvairāk noslogotos pakalpojumus izvietot atseviŔķi, lai netērētu resursus un iegÅ«tu elastÄ«gāku kontroli pār mÅ«su izvietoÅ”anas shēmu.

Grūti ieviest mūsdienu tehnoloģijas
Problēma, kas pazÄ«stama visiem izstrādātājiem: ir vēlme projektā ieviest modernās tehnoloÄ£ijas, bet nav iespēju. Izmantojot lielu monolÄ«tu risinājumu, jebkurÅ” paÅ”reizējās bibliotēkas atjauninājums, nemaz nerunājot par pāreju uz jaunu, pārvērÅ”as par diezgan netriviālu uzdevumu. Ir nepiecieÅ”ams ilgs laiks, lai pierādÄ«tu komandas vadÄ«tājam, ka tas dos vairāk bonusu nekā iztērēti nervi.

Grūtības izdot izmaiņas
Å Ä« bija visnopietnākā problēma ā€” mēs izlaidām ik pēc diviem mēneÅ”iem.
Katrs laidiens bankai kļuva par īstu katastrofu, neskatoties uz izstrādātāju testiem un centieniem. Uzņēmums saprata, ka nedēļas sākumā daļa tā funkcionalitātes nedarbosies. Un izstrādātāji saprata, ka viņus gaida nopietnu incidentu nedēļa.
Ikvienam bija vēlme mainīt situāciju.

Cerības no mikropakalpojumiem


Sastāvdaļu problēma, kad tā ir gatava. Sastāvdaļu piegāde, kad tās ir gatavas, sadalot Ŕķīdumu un atdalot dažādus procesus.

Mazas produktu komandas. Tas ir svarÄ«gi, jo lielu komandu, kas strādāja pie vecā monolÄ«ta, bija grÅ«ti vadÄ«t. Šāda komanda bija spiesta strādāt pēc stingra procesa, taču viņi vēlējās vairāk radoÅ”uma un neatkarÄ«bas. To varēja atļauties tikai mazas komandas.

Pakalpojumu izolÄ“Å”ana atseviŔķos procesos. Ideālā gadÄ«jumā es gribēju to izolēt konteineros, taču liels skaits .NET Framework rakstÄ«to pakalpojumu darbojas tikai operētājsistēmā Windows. Tagad tiek parādÄ«ti pakalpojumi, kuru pamatā ir .NET Core, taču to vēl ir maz.

IzvietoÅ”anas elastÄ«ba. Mēs vēlētos apvienot pakalpojumus tā, kā mums tas ir nepiecieÅ”ams, nevis tā, kā kods to uzspiež.

Jauno tehnoloÄ£iju izmantoÅ”ana. Tas ir interesanti jebkuram programmētājam.

Pārejas problēmas


Protams, ja monolÄ«tu bÅ«tu viegli sadalÄ«t mikropakalpojumos, par to nebÅ«tu jārunā konferencēs un jāraksta raksti. Å ajā procesā ir daudz nepilnÄ«bu, es aprakstÄ«Å”u galvenās, kas mums traucēja.

Pirmā problēma raksturÄ«gs lielākajai daļai monolÄ«tu: biznesa loÄ£ikas saskaņotÄ«ba. Kad mēs rakstām monolÄ«tu, mēs vēlamies atkārtoti izmantot savas klases, lai nerakstÄ«tu nevajadzÄ«gu kodu. Un, pārejot uz mikropakalpojumiem, tā kļūst par problēmu: viss kods ir diezgan cieÅ”i savienots, un pakalpojumus ir grÅ«ti nodalÄ«t.

Darba uzsākÅ”anas brÄ«dÄ« repozitorijā bija vairāk nekā 500 projektu un vairāk nekā 700 tÅ«kstoÅ”i koda rindu. Tas ir diezgan liels lēmums un otrā problēma. Nevarēja vienkārÅ”i paņemt un sadalÄ«t mikropakalpojumos.

TreŔā problēma ā€” nepiecieÅ”amās infrastruktÅ«ras trÅ«kums. Faktiski mēs manuāli kopējām avota kodu uz serveriem.

Kā pāriet no monolīta uz mikropakalpojumiem


Mikropakalpojumu nodroŔināŔana

Pirmkārt, mēs uzreiz paÅ”i noteicām, ka mikropakalpojumu atdalÄ«Å”ana ir iteratÄ«vs process. Mums vienmēr tika prasÄ«ts paralēli attÄ«stÄ«t biznesa problēmas. Kā mēs to tehniski Ä«stenosim, tā jau ir mÅ«su problēma. Tāpēc mēs sagatavojāmies iteratÄ«vam procesam. Tas nedarbosies citādi, ja jums ir liela lietojumprogramma un tā sākotnēji nav gatava pārrakstÄ«Å”anai.

Kādas metodes mēs izmantojam, lai izolētu mikropakalpojumus?

Pirmā metode ā€” pārvietot esoÅ”os moduļus kā pakalpojumus. Å ajā ziņā mums paveicās: jau bija reÄ£istrēti pakalpojumi, kas darbojās, izmantojot WCF protokolu. Tie tika sadalÄ«ti atseviŔķās asamblejās. Mēs tos pārnēsājām atseviŔķi, katrai bÅ«vei pievienojot nelielu palaiÅ”anas programmu. Tas tika uzrakstÄ«ts, izmantojot brÄ«niŔķīgo Topshelf bibliotēku, kas ļauj palaist lietojumprogrammu gan kā pakalpojumu, gan kā konsoli. Tas ir ērti atkļūdoÅ”anai, jo risinājumā nav nepiecieÅ”ami papildu projekti.

Pakalpojumi tika savienoti saskaņā ar biznesa loÄ£iku, jo tie izmantoja kopējus mezglus un strādāja ar kopÄ«gu datu bāzi. Diez vai tos varētu saukt par mikropakalpojumiem tÄ«rā veidā. Taču Å”os pakalpojumus mēs varētu sniegt atseviŔķi, dažādos procesos. Tas vien ļāva samazināt to ietekmi vienam uz otru, samazinot problēmu ar paralēlu attÄ«stÄ«bu un vienu neveiksmes punktu.

Montāža ar resursdatoru ir tikai viena koda rindiņa Programmas klasē. Mēs slēpām darbu ar Topshelf palīgklasē.

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

       }
    }
}

Otrs veids, kā pieŔķirt mikropakalpojumus, ir: izveidot tos jaunu problēmu risināŔanai. Ja tajā paŔā laikā monolÄ«ts neaug, tas jau ir lieliski, kas nozÄ«mē, ka mēs virzāmies pareizajā virzienā. Lai atrisinātu jaunas problēmas, mēģinājām izveidot atseviŔķus pakalpojumus. Ja bija tāda iespēja, tad izveidojām ā€œkanoniskākusā€ servisus, kas pilnÄ«bā pārvalda savu datu modeli, atseviŔķu datu bāzi.

Mēs, tāpat kā daudzi, sākām ar autentifikācijas un autorizācijas pakalpojumiem. Tie ir ideāli piemēroti Å”im nolÅ«kam. Tie ir neatkarÄ«gi, kā likums, tiem ir atseviŔķs datu modelis. Viņi paÅ”i nesadarbojas ar monolÄ«tu, tikai tas vērÅ”as pie viņiem, lai atrisinātu dažas problēmas. Izmantojot Å”os pakalpojumus, varat sākt pāreju uz jaunu arhitektÅ«ru, atkļūdot tajos esoÅ”o infrastruktÅ«ru, izmēģināt dažas ar tÄ«kla bibliotēkām saistÄ«tas pieejas utt. MÅ«su organizācijā nav nevienas komandas, kas nevarētu izveidot autentifikācijas pakalpojumu.

TreÅ”ais veids, kā pieŔķirt mikropakalpojumusTas, ko mēs izmantojam, mums ir nedaudz specifisks. Tā ir biznesa loÄ£ikas noņemÅ”ana no lietotāja interfeisa slāņa. MÅ«su galvenā lietotāja saskarnes lietojumprogramma ir darbvirsma; tā, tāpat kā aizmugure, ir rakstÄ«ta C#. Izstrādātāji periodiski pieļāva kļūdas un pārsÅ«tÄ«ja uz lietotāja saskarni loÄ£ikas daļas, kurām vajadzēja pastāvēt aizmugursistēmā un izmantot atkārtoti.

Ja paskatās uz reālu piemēru no UI daļas koda, jÅ«s varat redzēt, ka lielākā daļa Ŕī risinājuma satur reālu biznesa loÄ£iku, kas ir noderÄ«ga citos procesos, ne tikai UI veidlapas veidoÅ”anā.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

ÄŖstā lietotāja interfeisa loÄ£ika ir tikai pēdējās pāris rindiņās. Mēs to pārsÅ«tÄ«jām uz serveri, lai to varētu izmantot atkārtoti, tādējādi samazinot lietotāja interfeisu un panākot pareizo arhitektÅ«ru.

Ceturtais un vissvarÄ«gākais veids, kā izolēt mikropakalpojumus, kas ļauj samazināt monolÄ«tu, ir esoÅ”o pakalpojumu noņemÅ”ana ar apstrādi. Ja mēs izņemam esoÅ”os moduļus tādus, kādi tie ir, rezultāts ne vienmēr atbilst izstrādātājiem, un biznesa process var bÅ«t novecojis kopÅ” funkcionalitātes izveides. Izmantojot pārstrukturÄ“Å”anu, mēs varam atbalstÄ«t jaunu biznesa procesu, jo biznesa prasÄ«bas pastāvÄ«gi mainās. Mēs varam uzlabot avota kodu, novērst zināmos defektus un izveidot labāku datu modeli. Uzkrāsies daudz priekÅ”rocÄ«bu.

Pakalpojumu nodalÄ«Å”ana no apstrādes ir nesaraujami saistÄ«ta ar ierobežota konteksta jēdzienu. Å Ä« ir domēna vadÄ«ta dizaina koncepcija. Tas nozÄ«mē domēna modeļa sadaļu, kurā visi vienas valodas termini ir unikāli definēti. ApskatÄ«sim apdroÅ”ināŔanas un rēķinu konteksta piemēru. Mums ir monolÄ«ta lietojumprogramma, un mums ir jāstrādā ar kontu apdroÅ”ināŔanā. Mēs sagaidām, ka izstrādātājs atradÄ«s esoÅ”u konta klasi citā komplektā, atsaucēs uz to no apdroÅ”ināŔanas klases, un mums bÅ«s darba kods. Tiks ievērots DRY princips, uzdevums tiks paveikts ātrāk, izmantojot esoÅ”o kodu.

Rezultātā izrādās, ka kontu un apdroÅ”ināŔanas konteksti ir saistÄ«ti. Parādoties jaunām prasÄ«bām, Ŕī sakabe traucēs attÄ«stÄ«bai, palielinot jau tā sarežģītās biznesa loÄ£ikas sarežģītÄ«bu. Lai atrisinātu Å”o problēmu, kodā jāatrod robežas starp kontekstiem un jānovērÅ” to pārkāpumi. Piemēram, apdroÅ”ināŔanas kontekstā pilnÄ«gi iespējams, ka pietiks ar 20 ciparu Centrālās bankas konta numuru un konta atvērÅ”anas datumu.

Lai atdalÄ«tu Å”os ierobežotos kontekstus vienu no otra un sāktu mikropakalpojumu atdalÄ«Å”anas procesu no monolÄ«ta risinājuma, mēs izmantojām tādu pieeju kā ārējo API izveidoÅ”ana lietojumprogrammā. Ja mēs zinājām, ka kādam modulim ir jākļūst par mikropakalpojumu, kaut kā modificētam procesa gaitā, tad ar ārējiem izsaukumiem nekavējoties izsaucām loÄ£iku, kas pieder citam ierobežotam kontekstam. Piemēram, izmantojot REST vai WCF.

Mēs stingri nolēmām, ka neizvairÄ«simies no koda, kas prasÄ«s izplatÄ«tus darÄ«jumus. MÅ«su gadÄ«jumā izrādÄ«jās, ka ir diezgan viegli ievērot Å”o noteikumu. Mēs vēl neesam saskāruÅ”ies ar situācijām, kad patieŔām bÅ«tu nepiecieÅ”amas stingri sadalÄ«tas transakcijas - galÄ«gā konsekvence starp moduļiem ir diezgan pietiekama.

ApskatÄ«sim konkrētu piemēru. Mums ir orÄ·estra jēdziens ā€” konveijera, kas apstrādā ā€œlietojumprogrammasā€ entÄ«tiju. ViņŔ pēc kārtas izveido klientu, kontu un bankas karti. Ja klients un konts ir izveidots veiksmÄ«gi, bet kartes izveide neizdodas, lietojumprogramma nepāriet uz ā€œveiksmÄ«gaā€ statusu un paliek ā€œkarte nav izveidotaā€ statusā. Turpmāk fona darbÄ«bas to uztvers un pabeigs. Sistēma jau kādu laiku ir bijusi nekonsekvences stāvoklÄ«, taču kopumā esam apmierināti ar to.

Ja radīsies situācija, kad ir nepiecieŔams konsekventi saglabāt daļu datu, visticamāk, dosimies uz pakalpojuma konsolidāciju, lai to apstrādātu vienā procesā.

ApskatÄ«sim mikropakalpojuma pieŔķirÅ”anas piemēru. Kā to var salÄ«dzinoÅ”i droÅ”i nogādāt ražoÅ”anā? Å ajā piemērā mums ir atseviŔķa sistēmas daļa - algas apkalpoÅ”anas modulis, kura vienu no koda sadaļām vēlamies izveidot mikroservisu.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Pirmkārt, mēs izveidojam mikropakalpojumu, pārrakstot kodu. Mēs uzlabojam dažus aspektus, ar kuriem mēs nebijām apmierināti. Mēs ievieÅ”am jaunas biznesa prasÄ«bas no klienta puses. Mēs pievienojam API vārteju savienojumam starp UI un aizmugursistēmu, kas nodroÅ”inās zvanu pāradresāciju.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Pēc tam mēs laižam Å”o konfigurāciju ekspluatācijā, bet izmēģinājuma stāvoklÄ«. Lielākā daļa mÅ«su lietotāju joprojām strādā ar veciem biznesa procesiem. Jaunajiem lietotājiem mēs izstrādājam jaunu monolÄ«tās lietojumprogrammas versiju, kurā vairs nav Ŕī procesa. BÅ«tÄ«bā mums ir monolÄ«ta un mikropakalpojuma kombinācija, kas darbojas kā pilots.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Ar veiksmÄ«gu izmēģinājuma versiju mēs saprotam, ka jaunā konfigurācija patieŔām ir funkcionāla, mēs varam noņemt veco monolÄ«tu no vienādojuma un atstāt jauno konfigurāciju vecā risinājuma vietā.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Kopumā mēs izmantojam gandrÄ«z visas esoŔās metodes monolÄ«ta avota koda sadalÄ«Å”anai. Visi no tiem ļauj mums samazināt lietojumprogrammas daļu lielumu un pārtulkot tās jaunās bibliotēkās, padarot labāku pirmkodu.

Darbs ar datu bāzi


Datu bāzi var sadalÄ«t sliktāk nekā avota kodu, jo tajā ir ne tikai paÅ”reizējā shēma, bet arÄ« uzkrātie vēsturiskie dati.

Mūsu datubāzei, tāpat kā daudzām citām, bija vēl viens būtisks trūkums - tās milzīgais izmērs. Šī datu bāze tika veidota saskaņā ar sarežģīto monolīta biznesa loģiku un attiecībām, kas uzkrātas starp dažādu ierobežotu kontekstu tabulām.

MÅ«su gadÄ«jumā, lai papildinātu visas nepatikÅ”anas (liela datu bāze, daudzi savienojumi, dažreiz neskaidras robežas starp tabulām), radās problēma, kas rodas daudzos lielos projektos: koplietotās datu bāzes veidnes izmantoÅ”ana. Dati tika ņemti no tabulām caur skatu, izmantojot replikāciju un nosÅ«tÄ«ti uz citām sistēmām, kur Ŕī replikācija bija nepiecieÅ”ama. Tā rezultātā mēs nevarējām pārvietot tabulas atseviŔķā shēmā, jo tās tika aktÄ«vi izmantotas.

Tas pats iedalÄ«jums ierobežotos kontekstos kodā palÄ«dz mums atdalÄ«ties. Tas parasti sniedz mums diezgan labu priekÅ”statu par to, kā mēs sadalām datus datu bāzes lÄ«menÄ«. Mēs saprotam, kuras tabulas pieder vienam ierobežotam kontekstam un kuras citam.

Mēs izmantojām divas globālas datu bāzes sadalÄ«Å”anas metodes: esoÅ”o tabulu sadalÄ«Å”anu un sadalÄ«Å”anu ar apstrādi.

EsoÅ”o tabulu sadalÄ«Å”ana ir laba metode, ko izmantot, ja datu struktÅ«ra ir laba, atbilst biznesa prasÄ«bām un visi ir ar to apmierināti. Å ajā gadÄ«jumā esoŔās tabulas varam atdalÄ«t atseviŔķā shēmā.

Nodaļa ar apstrādi ir vajadzīga, kad biznesa modelis ir ļoti mainījies, un tabulas mūs vairs neapmierina.

EsoÅ”o tabulu sadalÄ«Å”ana. Mums ir jānosaka, ko mēs atdalÄ«sim. Bez Ŕīm zināŔanām nekas nedarbosies, un Å”eit mums palÄ«dzēs ierobežoto kontekstu atdalÄ«Å”ana kodā. Parasti, ja jÅ«s varat saprast kontekstu robežas avota kodā, kļūst skaidrs, kuras tabulas jāiekļauj nodaļas sarakstā.

Iedomāsimies, ka mums ir risinājums, kurā divi monolÄ«ti moduļi mijiedarbojas ar vienu datu bāzi. Mums ir jāpārliecinās, ka tikai viens modulis mijiedarbojas ar atdalÄ«to tabulu sadaļu, bet otrs sāk mijiedarboties ar to, izmantojot API. Sākumā pietiek ar to, ka caur API tiek veikta tikai ierakstÄ«Å”ana. Tas ir nepiecieÅ”ams nosacÄ«jums, lai mēs varētu runāt par mikropakalpojumu neatkarÄ«bu. LasÄ«Å”anas savienojumi var saglabāties tik ilgi, kamēr nav lielu problēmu.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Nākamais solis ir tas, ka mēs varam atdalÄ«t koda sadaļu, kas darbojas ar atdalÄ«tām tabulām, ar vai bez apstrādes, atseviŔķā mikropakalpojumā un palaist to atseviŔķā procesā, konteinerā. Tas bÅ«s atseviŔķs pakalpojums ar savienojumu ar monolÄ«tu datu bāzi un tām tabulām, kas ar to tieÅ”i neattiecas. MonolÄ«ts joprojām mijiedarbojas lasÄ«Å”anai ar noņemamo daļu.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Vēlāk mēs noņemsim Å”o savienojumu, tas ir, datu nolasÄ«Å”ana no monolÄ«tās lietojumprogrammas no atdalÄ«tām tabulām tiks pārsÅ«tÄ«ta arÄ« uz API.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Tālāk no vispārējās datu bāzes atlasÄ«sim tabulas, ar kurām strādā tikai jaunais mikropakalpojums. Mēs varam pārvietot tabulas uz atseviŔķu shēmu vai pat uz atseviŔķu fizisku datu bāzi. Joprojām ir lasÄ«Å”anas savienojums starp mikroservisu un monolÄ«tu datu bāzi, taču nav par ko uztraukties, Ŕādā konfigurācijā tā var dzÄ«vot diezgan ilgu laiku.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Pēdējais solis ir pilnÄ«bā noņemt visus savienojumus. Šādā gadÄ«jumā mums var bÅ«t nepiecieÅ”ams migrēt datus no galvenās datu bāzes. Dažreiz mēs vēlamies atkārtoti izmantot dažus datus vai direktorijus, kas replicēti no ārējām sistēmām vairākās datu bāzēs. Pie mums tas notiek periodiski.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Apstrādes nodaļa. Å Ä« metode ir ļoti lÄ«dzÄ«ga pirmajai, tikai apgrieztā secÄ«bā. Mēs nekavējoties pieŔķiram jaunu datu bāzi un jaunu mikropakalpojumu, kas mijiedarbojas ar monolÄ«tu, izmantojot API. Bet tajā paŔā laikā paliek datu bāzes tabulu kopa, kuru mēs vēlamies dzēst nākotnē. Mums tas vairs nav vajadzÄ«gs; mēs to nomainÄ«jām jaunajā modelÄ«.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Lai Ŕī shēma darbotos, mums, visticamāk, bÅ«s nepiecieÅ”ams pārejas periods.

Tad ir divas iespējamās pieejas.

Pirmais: mēs dublējam visus datus jaunajā un vecajā datubāzē. Å ajā gadÄ«jumā mums ir datu dublÄ“Å”ana un var rasties sinhronizācijas problēmas. Bet mēs varam uzņemt divus dažādus klientus. Viens darbosies ar jauno versiju, otrs ar veco.

Otrais: mēs sadalām datus pēc dažiem biznesa kritērijiem. Piemēram, mums sistēmā bija 5 produkti, kas tika saglabāti vecajā datu bāzē. Sesto ievietojam jaunā biznesa uzdevuma ietvaros jaunā datu bāzē. Bet mums bÅ«s nepiecieÅ”ama API vārteja, kas sinhronizēs Å”os datus un parādÄ«s klientam, no kurienes un ko iegÅ«t.

Abas pieejas darbojas, izvēlieties atkarībā no situācijas.

Kad esam pārliecināti, ka viss darbojas, monolīta daļu, kas darbojas ar vecām datu bāzes struktūrām, var atspējot.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Pēdējais solis ir noņemt vecās datu struktūras.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Rezumējot, varam teikt, ka mums ir problēmas ar datu bāzi: ar to ir grÅ«ti strādāt, salÄ«dzinot ar avota kodu, grÅ«tāk koplietot, bet to var un vajag darÄ«t. Mēs esam atraduÅ”i dažus veidus, kas ļauj to izdarÄ«t diezgan droÅ”i, taču joprojām ir vieglāk kļūdÄ«ties ar datiem, nevis ar pirmkodu.

Darbs ar pirmkodu


Šādi izskatījās pirmkoda diagramma, kad sākām analizēt monolītu projektu.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

To var aptuveni sadalÄ«t trÄ«s slāņos. Å is ir palaistu moduļu, spraudņu, pakalpojumu un atseviŔķu darbÄ«bu slānis. Faktiski tie bija ieejas punkti monolÄ«tā risinājumā. Visi tie bija cieÅ”i noslēgti ar kopējo slāni. Tam bija biznesa loÄ£ika, ko pakalpojumi koplietoja, un daudz savienojumu. Katrs pakalpojums un spraudnis izmantoja lÄ«dz pat 10 vai vairāk izplatÄ«tu komplektu atkarÄ«bā no to lieluma un izstrādātāju sirdsapziņas.

Mums paveicās ar infrastruktÅ«ras bibliotēkām, kuras varēja izmantot atseviŔķi.

Dažkārt radās situācija, kad daži kopÄ«gi objekti faktiski nepiederēja Å”im slānim, bet bija infrastruktÅ«ras bibliotēkas. Tas tika atrisināts, pārdēvējot.

Vislielākās bažas radÄ«ja ierobežotie konteksti. GadÄ«jās, ka 3-4 konteksti tika sajaukti vienā kopējā komplektācijā un viens otru izmantoja vienās un tajās paŔās biznesa funkcijās. Bija jāsaprot, kur to var sadalÄ«t un pa kādām robežām, un ko darÄ«t tālāk, kartējot Å”o sadalÄ«jumu avota koda komplektos.

Mēs esam formulējuÅ”i vairākus noteikumus koda sadalÄ«Å”anas procesam.

Pirmais: mēs vairs nevēlējāmies koplietot biznesa loÄ£iku starp pakalpojumiem, darbÄ«bām un spraudņiem. Mēs vēlējāmies padarÄ«t biznesa loÄ£iku neatkarÄ«gu mikropakalpojumos. No otras puses, mikropakalpojumi ideālā gadÄ«jumā tiek uzskatÄ«ti par pakalpojumiem, kas pastāv pilnÄ«gi neatkarÄ«gi. Uzskatu, ka Ŕāda pieeja ir zināmā mērā izŔķērdÄ«ga un grÅ«ti panākama, jo, piemēram, servisi C# valodā jebkurā gadÄ«jumā tiks savienoti ar standarta bibliotēku. MÅ«su sistēma ir rakstÄ«ta C#, citas tehnoloÄ£ijas mēs vēl neesam izmantojuÅ”i. Tāpēc nolēmām, ka varam atļauties izmantot kopÄ«gus tehniskos mezglus. Galvenais, lai tie nesatur nekādus biznesa loÄ£ikas fragmentus. Ja jÅ«su izmantotajam ORM ir ērts iesaiņojums, tā kopÄ“Å”ana no pakalpojuma uz pakalpojumu ir ļoti dārga.

MÅ«su komanda ir domēna virzÄ«ta dizaina cienÄ«tāja, tāpēc sÄ«polu arhitektÅ«ra mums bija lieliski piemērota. MÅ«su pakalpojumu pamatā ir nevis datu piekļuves slānis, bet gan komplekss ar domēna loÄ£iku, kas satur tikai biznesa loÄ£iku un nav saistÄ«ts ar infrastruktÅ«ru. Tajā paŔā laikā mēs varam neatkarÄ«gi modificēt domēna komplektu, lai atrisinātu ar ietvariem saistÄ«tas problēmas.

Å ajā posmā mēs saskārāmies ar savu pirmo nopietno problēmu. Pakalpojumam bija jāatsaucas uz vienu domēna komplektu, mēs vēlējāmies padarÄ«t loÄ£iku neatkarÄ«gu, un DRY princips mums Å”eit ļoti traucēja. Izstrādātāji vēlējās atkārtoti izmantot klases no blakus esoÅ”ajiem kompleksiem, lai izvairÄ«tos no dublÄ“Å”anās, un rezultātā domēni atkal sāka saistÄ«t kopā. Mēs analizējām rezultātus un nolēmām, ka, iespējams, problēma ir arÄ« avota koda atmiņas ierÄ«ces jomā. Mums bija liels repozitorijs, kurā bija viss avota kods. Visa projekta risinājumu bija ļoti grÅ«ti salikt vietējā maŔīnā. Tāpēc projekta daļām tika izveidoti atseviŔķi mazi risinājumi, un neviens neaizliedza tiem pievienot kādu kopÄ«gu vai domēna komplektāciju un izmantot atkārtoti. VienÄ«gais rÄ«ks, kas mums neļāva to izdarÄ«t, bija koda pārskatÄ«Å”ana. Bet dažreiz tas arÄ« neizdevās.

Pēc tam mēs sākām pāriet uz modeli ar atseviŔķām krātuvēm. Biznesa loÄ£ika vairs neplÅ«st no pakalpojuma uz pakalpojumu, domēni ir patiesi kļuvuÅ”i neatkarÄ«gi. Ierobežoti konteksti tiek atbalstÄ«ti skaidrāk. Kā mēs atkārtoti izmantojam infrastruktÅ«ras bibliotēkas? Mēs tos sadalÄ«jām atseviŔķā repozitorijā, pēc tam ievietojām Nuget pakotnēs, kuras ievietojām artifactory. Veicot jebkādas izmaiņas, montāža un publicÄ“Å”ana notiek automātiski.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

MÅ«su pakalpojumi sāka atsaukties uz iekŔējām infrastruktÅ«ras pakotnēm tāpat kā uz ārējām. Mēs lejupielādējam ārējās bibliotēkas no Nuget. Lai strādātu ar Artifactory, kur ievietojām Ŕīs pakotnes, mēs izmantojām divus pakotņu pārvaldniekus. Mazajās krātuvēs mēs izmantojām arÄ« Nuget. Repozitorijās ar vairākiem pakalpojumiem mēs izmantojām Paket, kas nodroÅ”ina lielāku versiju konsekvenci starp moduļiem.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Tādējādi, strādājot pie pirmkoda, nedaudz mainot arhitektūru un atdalot repozitorijus, mēs padarām savus pakalpojumus neatkarīgākus.

Infrastruktūras problēmas


Lielākā daļa negatÄ«vo aspektu, kas saistÄ«ti ar pāreju uz mikropakalpojumiem, ir saistÄ«ti ar infrastruktÅ«ru. Jums bÅ«s nepiecieÅ”ama automatizēta izvietoÅ”ana, jums bÅ«s nepiecieÅ”amas jaunas bibliotēkas, lai palaistu infrastruktÅ«ru.

Manuāla uzstādÄ«Å”ana vidēs

Sākotnēji risinājumu vidēm uzstādÄ«jām manuāli. Lai automatizētu Å”o procesu, mēs izveidojām CI/CD konveijeru. Mēs izvēlējāmies nepārtrauktas piegādes procesu, jo nepārtraukta izvietoÅ”ana mums vēl nav pieņemama no biznesa procesu viedokļa. Tāpēc nosÅ«tÄ«Å”ana darbÄ«bai tiek veikta, izmantojot pogu, un pārbaudei - automātiski.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Mēs izmantojam Atlassian, Bitbucket pirmkoda glabāŔanai un Bamboo bÅ«vÄ“Å”anai. Mums patÄ«k rakstÄ«t veidoÅ”anas skriptus programmā Cake, jo tas ir tas pats, kas C#. Gatavās pakotnes nonāk Artifactory, un Ansible automātiski nokļūst testa serveros, pēc tam tās var nekavējoties pārbaudÄ«t.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

AtseviŔķa mežizstrāde


Savulaik viena no monolÄ«ta idejām bija nodroÅ”ināt kopÄ«gu mežizstrādi. Mums arÄ« bija jāsaprot, ko darÄ«t ar atseviŔķiem diskos esoÅ”ajiem žurnāliem. MÅ«su žurnāli tiek ierakstÄ«ti teksta failos. Mēs nolēmām izmantot standarta ELK kaudzi. Mēs nerakstÄ«jām ELK tieÅ”i caur pakalpojumu sniedzējiem, bet nolēmām, ka modificēsim teksta žurnālus un ierakstÄ«sim tajos izsekoÅ”anas ID kā identifikatoru, pievienojot pakalpojuma nosaukumu, lai vēlāk Å”os žurnālus varētu parsēt.

Pāreja no monolīta uz mikropakalpojumiem: vēsture un prakse

Izmantojot Filebeat, mēs iegÅ«stam iespēju apkopot savus žurnālus no serveriem, pēc tam tos pārveidot, izmantot Kibana, lai izveidotu vaicājumus lietotāja saskarnē un redzētu, kā notika zvans starp pakalpojumiem. IzsekoÅ”anas ID Å”ajā jautājumā ļoti palÄ«dz.

Ar testÄ“Å”anu un atkļūdoÅ”anu saistÄ«ti pakalpojumi


Sākotnēji mēs pilnÄ«bā nesapratām, kā atkļūdot pakalpojumus, kas tiek izstrādāti. Ar monolÄ«tu viss bija vienkārÅ”i; mēs to izmantojām vietējā maŔīnā. Sākumā viņi mēģināja darÄ«t to paÅ”u ar mikropakalpojumiem, taču dažreiz, lai pilnÄ«bā palaistu vienu mikropakalpojumu, ir jāpalaiž vairāki citi, un tas ir neērti. Mēs sapratām, ka mums ir jāpāriet uz modeli, kurā vietējā maŔīnā atstājam tikai pakalpojumu vai pakalpojumus, kurus vēlamies atkļūdot. Pārējie pakalpojumi tiek izmantoti no serveriem, kas atbilst konfigurācijai ar prod. Pēc atkļūdoÅ”anas, testÄ“Å”anas laikā katram uzdevumam testa serverim tiek izsniegti tikai mainÄ«tie pakalpojumi. Tādējādi risinājums tiek testēts tādā formā, kādā tas nākotnē parādÄ«sies ražoÅ”anā.

Ir serveri, kuros darbojas tikai pakalpojumu ražoÅ”anas versijas. Å ie serveri ir nepiecieÅ”ami incidentu gadÄ«jumā, lai pārbaudÄ«tu piegādi pirms izvietoÅ”anas un lai veiktu iekŔējo apmācÄ«bu.

Mēs esam pievienojuÅ”i automatizētu testÄ“Å”anas procesu, izmantojot populāro Specflow bibliotēku. Testi tiek veikti automātiski, izmantojot NUnit tÅ«lÄ«t pēc izvietoÅ”anas no Ansible. Ja uzdevumu pārklājums ir pilnÄ«bā automātisks, manuāla pārbaude nav nepiecieÅ”ama. Lai gan dažreiz joprojām ir nepiecieÅ”ama papildu manuāla pārbaude. Mēs izmantojam Jira tagus, lai noteiktu, kuri testi jāveic konkrētai problēmai.

Turklāt ir pieaugusi nepiecieÅ”amÄ«ba pēc slodzes testÄ“Å”anas, iepriekÅ” tā tika veikta tikai retos gadÄ«jumos. Mēs izmantojam JMeter, lai palaistu testus, InfluxDB, lai tos saglabātu, un Grafana, lai izveidotu procesa grafikus.

Ko esam sasnieguŔi?


Pirmkārt, mēs atbrÄ«vojāmies no jēdziena ā€œatbrÄ«voÅ”anaā€. Ir pagājuÅ”i divu mēneÅ”u milzÄ«gie izlaidumi, kad Å”is koloss tika izvietots ražoÅ”anas vidē, Ä«slaicÄ«gi traucējot biznesa procesus. Tagad mēs izvietojam pakalpojumus vidēji ik pēc 1,5 dienām, grupējot tos, jo tie tiek nodoti ekspluatācijā pēc apstiprināŔanas.

Mūsu sistēmā nav fatālu kļūmju. Ja mēs izlaidīsim mikropakalpojumu ar kļūdu, ar to saistītā funkcionalitāte tiks bojāta, un visas pārējās funkcionalitātes netiks ietekmētas. Tas ievērojami uzlabo lietotāja pieredzi.

Mēs varam kontrolēt izvietoÅ”anas modeli. Ja nepiecieÅ”ams, varat atlasÄ«t pakalpojumu grupas atseviŔķi no pārējā risinājuma.

Turklāt mēs esam ievērojami samazinājuÅ”i problēmu ar lielu uzlabojumu rindu. Tagad mums ir atseviŔķas produktu komandas, kas ar dažiem pakalpojumiem strādā neatkarÄ«gi. Scrum process jau Å”eit ir piemērots. Konkrētai komandai var bÅ«t atseviŔķs produkta Ä«paÅ”nieks, kas tai pieŔķir uzdevumus.

Kopsavilkums

  • Mikropakalpojumi ir labi piemēroti sarežģītu sistēmu sadalÄ«Å”anai. Å ajā procesā mēs sākam saprast, kas ir mÅ«su sistēmā, kādi ir ierobežoti konteksti, kur ir to robežas. Tas ļauj pareizi sadalÄ«t uzlabojumus starp moduļiem un novērst koda sajaukÅ”anu.
  • Mikropakalpojumi sniedz organizatoriskas priekÅ”rocÄ«bas. Par tiem bieži runā tikai kā par arhitektÅ«ru, taču jebkura arhitektÅ«ra ir nepiecieÅ”ama biznesa vajadzÄ«bu risināŔanai, nevis pati par sevi. LÄ«dz ar to varam teikt, ka mikropakalpojumi ir labi piemēroti problēmu risināŔanai mazās komandās, ņemot vērā, ka Å”obrÄ«d Scrum ir ļoti populārs.
  • AtdalÄ«Å”ana ir iteratÄ«vs process. JÅ«s nevarat paņemt pieteikumu un vienkārÅ”i sadalÄ«t to mikropakalpojumos. IegÅ«tais produkts, visticamāk, nebÅ«s funkcionāls. PieŔķirot mikropakalpojumus, ir izdevÄ«gi pārrakstÄ«t esoÅ”o mantojumu, tas ir, pārvērst to par kodu, kas mums patÄ«k un labāk atbilst biznesa vajadzÄ«bām funkcionalitātes un ātruma ziņā.

    Neliels brÄ«dinājums: Izmaksas, pārejot uz mikropakalpojumiem, ir diezgan ievērojamas. Lai vienatnē atrisinātu infrastruktÅ«ras problēmu, bija nepiecieÅ”ams ilgs laiks. Tātad, ja jums ir neliela lietojumprogramma, kurai nav nepiecieÅ”ama Ä«paÅ”a mērogoÅ”ana, ja vien jums nav liels klientu skaits, kas sacenÅ”as par jÅ«su komandas uzmanÄ«bu un laiku, mikropakalpojumi var nebÅ«t tie, kas jums Å”odien ir nepiecieÅ”ami. Tas ir diezgan dārgi. Ja procesu sāksi ar mikropakalpojumiem, tad izmaksas sākotnēji bÅ«s lielākas nekā tad, ja tādu paÅ”u projektu uzsāksi ar monolÄ«ta izstrādi.

    PS Emocionālāks stāsts (un it kā jums personīgi) - saskaņā ar saite.
    Šeit ir pilna ziņojuma versija.

Avots: www.habr.com

Pievieno komentāru