Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

Selles artiklis rÀÀgin sellest, kuidas projekt, mille kallal töötan, muutus suurest monoliidist mikroteenuste komplektiks.

Projekt sai oma ajalugu alguse ĂŒsna kaua aega tagasi, 2000. aasta alguses. Esimesed versioonid kirjutati Visual Basic 6-s. Aja jooksul sai selgeks, et selle keele arendust on tulevikus raske toetada, kuna IDE ja keel ise on halvasti arenenud. 2000. aastate lĂ”pus otsustati ĂŒle minna paljulubavamale C#-le. Uus versioon kirjutati paralleelselt vana versiooniga, jĂ€rk-jĂ€rgult kirjutati aina rohkem koodi .NET-is. C# taustaprogramm keskendus algselt teenusearhitektuurile, kuid arenduse kĂ€igus kasutati tavalisi loogikaga teeke ja teenused kĂ€ivitati ĂŒhe protsessina. Tulemuseks oli rakendus, mida nimetasime teenuse monoliidiks.

Selle kombinatsiooni ĂŒks vĂ€heseid eeliseid oli teenuste vĂ”imalus ĂŒksteisele vĂ€lise API kaudu helistada. Korrektsemale teenusele ja tulevikus mikroteenuse arhitektuurile ĂŒleminekuks olid selged eeldused.

Alustasime lagunemisega tööd 2015. aasta paiku. Ideaalsesse seisu me veel jĂ”udnud ei ole – suurest projektist on veel osi, mida vaevalt monoliitideks nimetada saab, aga needki ei nĂ€e vĂ€lja nagu mikroteenused. Sellegipoolest on edasiminek mĂ€rkimisvÀÀrne.
Ma rÀÀgin sellest artiklis.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

Sisu

Olemasoleva lahenduse arhitektuur ja probleemid


Algselt nĂ€gi arhitektuur vĂ€lja selline: kasutajaliides on eraldi rakendus, monoliitne osa on kirjutatud Visual Basic 6-s, .NET-rakendus on seotud teenuste komplekt, mis töötab ĂŒsna suure andmebaasiga.

Eelmise lahenduse miinused

Üks ebaĂ”nnestumise punkt
Meil oli ĂŒksainus tĂ”rkepunkt: .NET-i rakendus töötas ĂŒhes protsessis. Kui mĂ”ni moodul ebaĂ”nnestus, ebaĂ”nnestus kogu rakendus ja see tuli taaskĂ€ivitada. Kuna automatiseerime suure hulga erinevate kasutajate protsesse, ei saanud ĂŒhes neist ĂŒhe rikke tĂ”ttu kĂ”ik mĂ”nda aega töötada. Ja tarkvara vea korral ei aidanud isegi varundamine.

Paranduste jÀrjekord
See puudus on pigem korralduslik. Meie rakendusel on palju kliente ja nad kĂ”ik soovivad seda vĂ”imalikult kiiresti tĂ€iustada. Varem ei saanud seda paralleelselt teha ja kĂ”ik kliendid seisid jĂ€rjekorras. See protsess oli ettevĂ”tete jaoks negatiivne, sest nad pidid tĂ”estama, et nende ĂŒlesanne on vÀÀrtuslik. Ja arendusmeeskond kulutas aega selle jĂ€rjekorra korraldamiseks. See vĂ”ttis palju aega ja vaeva ning lĂ”ppkokkuvĂ”ttes ei saanud toode nii kiiresti muutuda, kui nad oleks soovinud.

Mitteoptimaalne ressursside kasutamine
Teenuste ĂŒhe protsessi kĂ€igus hostimisel kopeerisime konfiguratsiooni alati tĂ€ielikult serverist serverisse. Tahtsime paigutada kĂ”ige rohkem koormatud teenused eraldi, et mitte raisata ressursse ja saavutada paindlikum kontroll oma juurutusskeemi ĂŒle.

Kaasaegseid tehnoloogiaid on keeruline rakendada
KĂ”igile arendajatele tuttav probleem: projekti tahetakse juurutada kaasaegseid tehnoloogiaid, aga vĂ”imalust pole. Suure monoliitse lahenduse korral muutub iga praeguse raamatukogu uuendamine, rÀÀkimata ĂŒleminekust uuele, ĂŒsna mittetriviaalseks ĂŒlesandeks. LĂ€heb kaua aega, enne kui meeskonnajuhile tĂ”estada, et see toob rohkem boonuseid kui raisatud nĂ€rve.

Raskused muudatuste vÀljastamisel
See oli kĂ”ige tĂ”sisem probleem – me andsime vĂ€lja iga kahe kuu tagant.
Vaatamata arendajate testimisele ja pingutustele muutus iga vÀljalase panga jaoks tÔeliseks katastroofiks. EttevÔte sai aru, et nÀdala alguses ei tööta mÔni selle funktsionaalsus. Ja arendajad mÔistsid, et neid ootab nÀdal tÔsiseid vahejuhtumeid.
KÔigil oli soov olukorda muuta.

Ootused mikroteenustele


Komponentide probleem, kui see on valmis. Komponentide tarnimine valmisolekul lahuse lagundamise ja erinevate protsesside eraldamise teel.

VÀikesed tootemeeskonnad. See on oluline, sest vana monoliidi kallal töötavat suurt meeskonda oli raske hallata. Selline meeskond oli sunnitud töötama range protsessi jÀrgi, kuid sooviti rohkem loovust ja iseseisvust. Seda said endale lubada vaid vÀikesed meeskonnad.

Teenuste eraldamine eraldi protsessides. Ideaalis tahaksin selle konteineritesse isoleerida, aga suur hulk .NET Frameworkis kirjutatud teenuseid töötab ainult all Windows.NET Core'il pĂ”hinevad teenused ilmuvad nĂŒĂŒd, kuid neid on veel vĂ€he.

Paindlikkus juurutamisel. Tahaksime teenuseid kombineerida nii, nagu me seda vajame, mitte nii, nagu kood seda sunnib.

Uute tehnoloogiate kasutamine. See on huvitav igale programmeerijale.

Üleminekuprobleemid


Muidugi, kui monoliiti oleks lihtne mikroteenusteks lÔhkuda, poleks vaja sellest konverentsidel rÀÀkida ja artikleid kirjutada. Selles protsessis on palju lÔkse, ma kirjeldan peamisi, mis meid takistasid.

Esimene probleem tĂŒĂŒpiline enamikule monoliitidele: Ă€riloogika sidusus. Kui kirjutame monoliiti, tahame oma klasse uuesti kasutada, et mitte kirjutada tarbetut koodi. Ja mikroteenustele ĂŒleminekul muutub see probleemiks: kogu kood on ĂŒsna tihedalt seotud ja teenuseid on keeruline eraldada.

Tööde alustamise ajal oli hoidlas ĂŒle 500 projekti ja ĂŒle 700 tuhande koodirea. See on ĂŒsna suur otsus ja teine ​​probleem. Ei olnud vĂ”imalik seda lihtsalt vĂ”tta ja mikroteenusteks jagada.

Kolmas probleem — vajaliku infrastruktuuri puudumine. Tegelikult kopeerisime lĂ€htekoodi serveritesse kĂ€sitsi.

Kuidas liikuda monoliidilt mikroteenustele


Mikroteenuste pakkumine

Esiteks tegime enda jaoks kohe kindlaks, et mikroteenuste eraldamine on iteratiivne protsess. Meilt nĂ”uti alati paralleelselt Ă€riprobleemide arendamist. See, kuidas me seda tehniliselt rakendame, on juba meie probleem. SeetĂ”ttu valmistusime korduvaks protsessiks. See ei tööta muul viisil, kui teil on suur rakendus ja see pole esialgu valmis ĂŒmberkirjutamiseks.

Milliseid meetodeid kasutame mikroteenuste isoleerimiseks?

Esimene tee — teisaldada olemasolevad moodulid teenustena. Sellega seoses meil vedas: juba oli registreeritud teenuseid, mis töötasid WCF-protokolli kasutades. Need jagati eraldi sĂ”lmedeks. Portisime need eraldi, lisades igale konstruktsioonile vĂ€ikese kĂ€ivitusprogrammi. See on kirjutatud imelise Topshelfi teegi abil, mis vĂ”imaldab rakendust kĂ€ivitada nii teenusena kui ka konsoolina. See on silumiseks mugav, kuna lahenduses pole vaja tĂ€iendavaid projekte.

Teenused ĂŒhendati vastavalt Ă€riloogikale, kuna nad kasutasid ĂŒhiseid kooste ja töötasid ĂŒhise andmebaasiga. Vaevalt saaks neid puhtal kujul mikroteenusteks nimetada. KĂŒll aga saaksime neid teenuseid osutada eraldi, erinevates protsessides. AinuĂŒksi see vĂ”imaldas vĂ€hendada nende mĂ”ju ĂŒksteisele, vĂ€hendades probleemi paralleelse arengu ja ĂŒhe tĂ”rkepunktiga.

Hostiga kokkupanek on programmiklassis vaid ĂŒks koodirida. Varjasime Topshelfiga tööd abiklassis.

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

       }
    }
}

Teine viis mikroteenuste eraldamiseks on: luua neid uute probleemide lahendamiseks. Kui monoliit samal ajal ei kasva, on see juba suurepĂ€rane, mis tĂ€hendab, et liigume Ă”iges suunas. Uute probleemide lahendamiseks pĂŒĂŒdsime luua eraldi teenuseid. Kui selline vĂ”imalus oli, siis lĂ”ime rohkem “kanoonilisi” teenuseid, mis haldavad tĂ€ielikult oma andmemudelit, eraldi andmebaasi.

Meie, nagu paljud, alustasime autentimis- ja autoriseerimisteenustega. Nad sobivad selleks suurepĂ€raselt. Need on sĂ”ltumatud, reeglina on neil eraldi andmemudel. Nad ise ei suhtle monoliidiga, vaid see pöördub mĂ”ne probleemi lahendamiseks nende poole. Neid teenuseid kasutades saate alustada ĂŒleminekut uuele arhitektuurile, siluda nende infrastruktuuri, proovida mĂ”nda vĂ”rguteekidega seotud lĂ€henemisviisi jne. Meie organisatsioonis ei ole ĂŒhtegi meeskonda, kes ei saaks autentimisteenust luua.

Kolmas viis mikroteenuste eraldamiseksSee, mida me kasutame, on meile pisut spetsiifiline. See on Ă€riloogika eemaldamine kasutajaliidese kihist. Meie peamine kasutajaliidese rakendus on töölaud; see, nagu ka taustaprogramm, on kirjutatud C# keeles. Arendajad tegid aeg-ajalt vigu ja kandsid kasutajaliidesesse ĂŒle loogika osad, mis oleksid pidanud taustaprogrammis olemas olema ja mida oleks pidanud uuesti kasutama.

Kui vaatate kasutajaliidese osa koodist reaalset nÀidet, nÀete, et suurem osa sellest lahendusest sisaldab reaalset Àriloogikat, mis on kasulik ka muudes protsessides, mitte ainult kasutajaliidese vormi koostamisel.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

Tegelik kasutajaliidese loogika on alles paaril viimasel real. Viisime selle ĂŒle serverisse, et seda saaks uuesti kasutada, vĂ€hendades seelĂ€bi kasutajaliidest ja saavutades Ă”ige arhitektuuri.

Neljas ja kÔige olulisem viis mikroteenuste isoleerimiseks, mis vÔimaldab monoliiti vÀhendada, on olemasolevate teenuste eemaldamine koos töötlemisega. Kui vÔtame olemasolevad moodulid vÀlja niisama, ei ole tulemus alati arendajatele meeldiv ning Àriprotsess vÔib olla funktsionaalsuse loomisest alates aegunud. Refaktoreerimisega saame toetada uut Àriprotsessi, sest ÀrinÔuded muutuvad pidevalt. Saame tÀiustada lÀhtekoodi, eemaldada teadaolevad vead ja luua parema andmemudeli. Kasu on palju.

Teenuste eraldamine töötlemisest on lahutamatult seotud piiratud konteksti mĂ”istega. See on domeenipĂ”hise disaini kontseptsioon. See tĂ€hendab domeenimudeli osa, milles kĂ”ik ĂŒhe keele terminid on ĂŒheselt mÀÀratletud. Vaatame nĂ€itena kindlustuse ja arvete konteksti. Meil on monoliitne rakendus ja peame kontoga kindlustuses töötama. Eeldame, et arendaja leiab mĂ”nest teisest komplektist olemasoleva kontoklassi, viitab sellele kindlustusklassist ja meil on töökood. Austatakse DRY pĂ”himĂ”tet, olemasolevat koodi kasutades saab ĂŒlesanne tehtud kiiremini.

Selle tulemusena selgub, et kontode ja kindlustuse kontekstid on omavahel seotud. Uute nÔuete ilmnemisel segab see sidumine arengut, suurendades niigi keerulise Àriloogika keerukust. Selle probleemi lahendamiseks peate koodis leidma piirid kontekstide vahel ja kÔrvaldama nende rikkumised. NÀiteks kindlustuse kontekstis on tÀiesti vÔimalik, et piisab 20-kohalisest Keskpanga kontonumbrist ja konto avamise kuupÀevast.

Nende piiratud kontekstide ĂŒksteisest eraldamiseks ja mikroteenuste monoliitsest lahendusest eraldamise protsessi alustamiseks kasutasime sellist lĂ€henemisviisi nagu rakenduses vĂ€liste API-de loomine. Kui teadsime, et mingist moodulist peaks saama mikroteenus, seda protsessi sees kuidagi muudetuna, siis tegime vĂ€liskĂ”nede kaudu kohe vĂ€ljakutsed teise piiratud konteksti kuuluvale loogikale. NĂ€iteks RESTi vĂ”i WCF-i kaudu.

Otsustasime kindlalt, et me ei vĂ€ldi koodi, mis nĂ”uab hajutatud tehinguid. Meie puhul osutus selle reegli jĂ€rgimine ĂŒsna lihtsaks. Me ei ole veel kohanud olukordi, kus rangelt hajutatud tehinguid oleks tĂ”esti vaja – lĂ”plik moodulitevaheline kooskĂ”la on tĂ€iesti piisav.

Vaatame konkreetset nĂ€idet. Meil on orkestri kontseptsioon – torujuhe, mis töötleb rakenduse olemit. Ta loob kordamööda kliendi, konto ja pangakaardi. Kui kliendi ja konto loomine Ă”nnestub, kuid kaardi loomine nurjub, siis rakendus ei liigu olekusse “Ennestunud” ja jÀÀb olekusse “Kaart pole loodud”. Tulevikus vĂ”tab taustategevus selle ĂŒles ja lĂ”petab. SĂŒsteem on olnud mĂ”nda aega ebaĂŒhtlases seisundis, kuid ĂŒldiselt oleme sellega rahul.

Kui tekib olukord, kus on vaja osa andmetest jĂ€rjepidevalt salvestada, lĂ€heme suure tĂ”enĂ€osusega teenuse koondamisele, et seda ĂŒhes protsessis töödelda.

Vaatame nĂ€idet mikroteenuse eraldamisest. Kuidas saate selle suhteliselt ohutult tootmisse viia? Antud nĂ€ites on meil sĂŒsteemist eraldi osa - palgateenuse moodul, mille ĂŒhe koodilĂ”iku tahaksime teha mikroteenuse.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

KĂ”igepealt loome koodi ĂŒmber kirjutades mikroteenuse. TĂ€iustame mĂ”ningaid aspekte, millega me rahul ei olnud. Rakendame kliendilt uusi Ă€rinĂ”udeid. Lisame kasutajaliidese ja taustaprogrammi vahelisele ĂŒhendusele API lĂŒĂŒsi, mis pakub kĂ”ne suunamist.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

JÀrgmisena vabastame selle konfiguratsiooni tööle, kuid pilootolekus. Enamik meie kasutajaid töötab endiselt vanade Àriprotsessidega. Uute kasutajate jaoks töötame vÀlja monoliitrakenduse uue versiooni, mis seda protsessi enam ei sisalda. PÔhimÔtteliselt on meil piloodina töötav kombinatsioon monoliidist ja mikroteenusest.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

Eduka piloottöö korral saame aru, et uus konfiguratsioon on tÔepoolest toimiv, saame vana monoliidi vÔrrandist eemaldada ja jÀtta uue konfiguratsiooni vana lahenduse asemele.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

KokkuvĂ”ttes kasutame monoliidi lĂ€htekoodi tĂŒkeldamiseks peaaegu kĂ”iki olemasolevaid meetodeid. KĂ”ik need vĂ”imaldavad meil vĂ€hendada rakenduse osade suurust ja tĂ”lkida need uutesse teekidesse, muutes parema lĂ€htekoodi.

Töö andmebaasiga


Andmebaasi saab jagada halvemini kui lÀhtekoodi, kuna see ei sisalda mitte ainult praegust skeemi, vaid ka kogutud ajaloolisi andmeid.

Meie andmebaasil, nagu paljudel teistelgi, oli veel ĂŒks oluline puudus – selle tohutu suurus. See andmebaas loodi monoliidi keeruka Ă€riloogika ja erinevate piiratud kontekstide tabelite vahel kogunenud suhete jĂ€rgi.

Meie puhul kerkis kĂ”igi hĂ€dade tipuks (suur andmebaas, palju ĂŒhendusi, kohati ebaselged piirid tabelite vahel) probleem, mis esineb paljudes suurtes projektides: jagatud andmebaasi malli kasutamine. Andmed vĂ”eti tabelitest lĂ€bi vaate, replikatsiooni ja saadeti teistesse sĂŒsteemidesse, kus seda replikatsiooni vaja oli. SeetĂ”ttu ei saanud me tabeleid eraldi skeemi liigutada, kuna neid kasutati aktiivselt.

Sama jaotus piiratud kontekstideks koodis aitab meil eraldada. Tavaliselt annab see meile ĂŒsna hea ĂŒlevaate sellest, kuidas andmeid andmebaasi tasemel jaotame. Saame aru, millised tabelid kuuluvad ĂŒhte piiratud konteksti ja millised teise.

Andmebaasi jaotamiseks kasutasime kahte globaalset meetodit: olemasolevate tabelite sektsioonideks jaotamiseks koos töötlemisega.

Olemasolevate tabelite eraldamine on hea meetod, mida kasutada, kui andmestruktuur on hea, vastab ÀrinÔuetele ja kÔik on sellega rahul. Sel juhul saame olemasolevad tabelid eraldada eraldi skeemiks.

Töötlemisega osakonda on vaja siis, kui Ă€rimudel on kĂ”vasti muutunud ja tabelid meid enam ĂŒldse ei rahulda.

Olemasolevate tabelite poolitamine. Peame otsustama, mida eraldame. Ilma nende teadmisteta ei tööta miski ja siin aitab meid piiritud kontekstide eraldamine koodis. Kui saate lÀhtekoodis kontekstide piiridest aru saada, saab reeglina selgeks, millised tabelid tuleks osakonna loendisse lisada.

Kujutagem ette, et meil on lahendus, kus kaks monoliitmoodulit suhtlevad ĂŒhe andmebaasiga. Peame tagama, et ainult ĂŒks moodul suhtleb eraldatud tabelite jaotisega ja teine ​​hakkab sellega API kaudu suhtlema. Alustuseks piisab, kui API kaudu toimub ainult salvestamine. See on vajalik tingimus, et saaksime rÀÀkida mikroteenuste iseseisvusest. LugemisĂŒhendused vĂ”ivad pĂŒsida seni, kuni pole suurt probleemi.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

JĂ€rgmine samm on see, et saame eraldada eraldatud tabelitega töötava koodiosa, töötlemisega vĂ”i ilma, eraldi mikroteenuseks ja kĂ€ivitada selle eraldi protsessis, konteineris. See on eraldi teenus, millel on ĂŒhendus monoliidi andmebaasi ja nende tabelitega, mis sellega otseselt ei ole seotud. Monoliit suhtleb lugemiseks endiselt eemaldatava osaga.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

Hiljem eemaldame selle ĂŒhenduse ehk ka monoliitsest rakendusest eraldatud tabelitest andmete lugemine kantakse API-sse.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

JĂ€rgmiseks valime ĂŒldandmebaasist vĂ€lja tabelid, millega töötab ainult uus mikroteenus. Saame liigutada tabelid eraldi skeemi vĂ”i isegi eraldi fĂŒĂŒsilisse andmebaasi. LugemisĂŒhendus mikroteenuse ja monoliitandmebaasi vahel on endiselt olemas, kuid muretsemiseks pole pĂ”hjust, sellises konfiguratsioonis vĂ”ib see pĂ€ris kaua elada.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

Viimane samm on kĂ”igi ĂŒhenduste tĂ€ielik eemaldamine. Sel juhul peame vĂ”ib-olla migreerima andmed pĂ”hiandmebaasist. MĂ”nikord tahame mĂ”nda vĂ€listest sĂŒsteemidest kopeeritud andmeid vĂ”i katalooge mitmes andmebaasis uuesti kasutada. Seda juhtub meiega perioodiliselt.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

Töötlemise osakond. See meetod on vÀga sarnane esimesele, ainult vastupidises jÀrjekorras. Eraldame kohe uue andmebaasi ja uue mikroteenuse, mis suhtleb monoliidiga API kaudu. Kuid samal ajal jÀÀb alles hulk andmebaasitabeleid, mida tahame tulevikus kustutada. Meil pole seda enam vaja; asendasime selle uues mudelis.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

Selle skeemi toimimiseks vajame tĂ”enĂ€oliselt ĂŒleminekuperioodi.

Siis on kaks vÔimalikku lÀhenemist.

Esimene: dubleerime kĂ”ik andmed uues ja vanas andmebaasis. Sel juhul on meil andmete liiasus ja vĂ”ivad tekkida sĂŒnkroonimisprobleemid. Kuid me saame vĂ”tta kaks erinevat klienti. Üks töötab uue versiooniga, teine ​​vana versiooniga.

Teine: jagame andmed mĂ”ne Ă€rikriteeriumi jĂ€rgi. NĂ€iteks oli meil sĂŒsteemis 5 toodet, mis olid salvestatud vanas andmebaasis. Kuuenda paigutame uue Ă€riĂŒlesande raames uude andmebaasi. Kuid meil on vaja API-lĂŒĂŒsi, mis sĂŒnkroonib need andmed ja nĂ€itab kliendile, kust ja mida saada.

MÔlemad lÀhenemisviisid töötavad, vali sÔltuvalt olukorrast.

Kui oleme veendunud, et kÔik töötab, saab vanade andmebaasistruktuuridega töötava monoliidi osa keelata.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

Viimane samm on vanade andmestruktuuride eemaldamine.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

KokkuvĂ”tteks vĂ”ib öelda, et meil on andmebaasiga probleeme: sellega on vĂ”rreldes lĂ€htekoodiga raske töötada, raskem jagada, aga saab ja peaks hakkama. Oleme leidnud mĂ”ned viisid, mis vĂ”imaldavad seda ĂŒsna turvaliselt teha, kuid andmetega on siiski lihtsam vigu teha kui lĂ€htekoodiga.

LÀhtekoodiga töötamine


Selline nĂ€gi lĂ€htekoodi diagramm vĂ€lja, kui hakkasime monoliitset projekti analĂŒĂŒsima.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

Selle saab laias laastus jagada kolmeks kihiks. See on kĂ€ivitatud moodulite, pistikprogrammide, teenuste ja individuaalsete tegevuste kiht. Tegelikult olid need monoliitse lahenduse sisenemispunktid. KĂ”ik need suleti tihedalt ĂŒhise kihiga. Sellel oli Ă€riloogika, mida teenused jagasid, ja palju ĂŒhendusi. Iga teenus ja pistikprogramm kasutas olenevalt nende suurusest ja arendajate sĂŒdametunnistusest kuni kĂŒmmet vĂ”i enamat tavalist komplekti.

Meil vedas, et meil olid infrastruktuuri raamatukogud, mida sai eraldi kasutada.

MĂ”nikord tekkis olukord, kus mĂ”ned levinud objektid ei kuulunud tegelikult sellesse kihti, vaid olid infrastruktuuri raamatukogud. See lahendati ĂŒmbernimetamisega.

Suurimaks murekohaks olid piiratud kontekstid. Juhtus, et 3-4 konteksti segati ĂŒhes ĂŒhises koosluses ja kasutati ĂŒksteist samade Ă€rifunktsioonide raames. Tuli aru saada, kuhu ja milliste piiride jĂ€rgi seda jagada saab ning mida edasi teha selle jaotuse kaardistamisega lĂ€htekoodikoostudeks.

Oleme koodi jagamise protsessi jaoks sÔnastanud mitu reeglit.

Esimene: me ei tahtnud enam Ă€riloogikat teenuste, tegevuste ja pistikprogrammide vahel jagada. Tahtsime muuta Ă€riloogika mikroteenuste sees sĂ”ltumatuks. Mikroteenuseid seevastu peetakse ideaalis teenusteks, mis eksisteerivad tĂ€iesti iseseisvalt. Usun, et selline lĂ€henemine on mĂ”nevĂ”rra raiskav ja seda on raske saavutada, sest nĂ€iteks C#-s olevad teenused ĂŒhendatakse igal juhul tavalise raamatukoguga. Meie sĂŒsteem on kirjutatud C# keeles, muid tehnoloogiaid me veel kasutanud ei ole. SeetĂ”ttu otsustasime, et saame endale lubada tavaliste tehniliste sĂ”lmede kasutamist. Peaasi, et need ei sisalda Ă€riloogika fragmente. Kui teil on kasutatava ORM-i kohal mugav ĂŒmbris, on selle kopeerimine teenusest teenusesse vĂ€ga kulukas.

Meie meeskond on domeenipÔhise disaini fÀnn, nii et sibularhitektuur sobis meile suurepÀraselt. Meie teenuste aluseks ei ole andmete juurdepÀÀsukiht, vaid domeeniloogikaga koost, mis sisaldab ainult Àriloogikat ja millel puudub seos infrastruktuuriga. Samal ajal saame domeenikomplekti iseseisvalt muuta, et lahendada raamistikega seotud probleeme.

Selles etapis puutusime kokku oma esimese tĂ”sise probleemiga. Teenus pidi viitama ĂŒhele domeenikoostule, tahtsime muuta loogika sĂ”ltumatuks ja DRY pĂ”himĂ”te takistas meid siin kĂ”vasti. Arendajad soovisid dubleerimise vĂ€ltimiseks naaberkoosluste klasse uuesti kasutada ja selle tulemusena hakati domeene uuesti omavahel siduma. AnalĂŒĂŒsisime tulemusi ja otsustasime, et vĂ”ib-olla peitub probleem ka lĂ€htekoodi salvestusseadme piirkonnas. Meil oli suur hoidla, mis sisaldas kogu lĂ€htekoodi. Kogu projekti lahendust oli kohalikul masinal vĂ€ga keeruline kokku panna. SeetĂ”ttu loodi projekti osade jaoks eraldi vĂ€ikelahendused ning keegi ei keelanud neile mingit ĂŒhist vĂ”i domeenikoosseisu lisada ja taaskasutada. Ainus tööriist, mis meil seda teha ei vĂ”imaldanud, oli koodi ĂŒlevaatus. Kuid mĂ”nikord see ka ebaĂ”nnestus.

SeejĂ€rel hakkasime liikuma eraldi hoidlate mudelile. Äriloogika ei liigu enam teenusest teenusesse, domeenid on muutunud tĂ”eliselt iseseisvaks. Piiratud kontekste toetatakse selgemalt. Kuidas me infrastruktuuri raamatukogusid taaskasutame? Eraldasime need eraldi hoidlasse, seejĂ€rel panime need Nugeti pakettidesse, mille panime Artifactorysse. Iga muudatuse korral toimub kokkupanek ja avaldamine automaatselt.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

Meie teenused hakkasid viitama sisemistele taristupakettidele samamoodi kui vÀlistele. Laadime Nugetist alla vÀliseid teeke. Artifactoryga töötamiseks, kuhu need paketid paigutasime, kasutasime kahte paketihaldurit. VÀikestes hoidlates kasutasime ka Nugetit. Mitme teenusega hoidlates kasutasime paketti, mis tagab moodulite vahel suurema versioonijÀrjepidevuse.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

Seega, töötades lÀhtekoodi kallal, muutes veidi arhitektuuri ja eraldades hoidlaid, muudame oma teenused sÔltumatumaks.

Infrastruktuuri probleemid


Enamik mikroteenustele ĂŒlemineku negatiivseid kĂŒlgi on seotud infrastruktuuriga. Teil on vaja automatiseeritud juurutamist, vajate infrastruktuuri kĂ€itamiseks uusi teeke.

KĂ€sitsi paigaldamine keskkondadesse

Algselt paigaldasime keskkondadele mÔeldud lahenduse kÀsitsi. Selle protsessi automatiseerimiseks lÔime CI/CD konveieri. Valisime pideva tarneprotsessi, kuna pidev juurutamine ei ole meie jaoks Àriprotsesside seisukohast veel vastuvÔetav. SeetÔttu toimub tööks saatmine nupu abil ja testimiseks - automaatselt.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

LÀhtekoodi salvestamiseks kasutame Atlassiani, Bitbucket ja ehitamiseks Bamboot. Meile meeldib Cake'is koostamisskripte kirjutada, kuna see on sama, mis C#. Artifactorysse tulevad valmis paketid ning Ansible jÔuab automaatselt testserveritesse, misjÀrel saab neid kohe testida.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

Eraldi metsaraie


Omal ajal oli ĂŒks monoliidi ideedest pakkuda ĂŒhisraiet. Samuti pidime mĂ”istma, mida teha plaatidel olevate ĂŒksikute logidega. Meie logid kirjutatakse tekstifailidesse. Otsustasime kasutada tavalist ELK virna. Otse pakkujate kaudu me ELK-le ei kirjutanud, vaid otsustasime, et muudame tekstiloge ja kirjutame neisse identifikaatorina jĂ€lje ID, lisades teenuse nime, et neid logisid saaks hiljem sĂ”eluda.

Üleminek monoliidilt mikroteenustele: ajalugu ja praktika

Filebeati abil saame oma logisid koguda jÀrgmistelt allikatelt: serverid, seejÀrel teisendage need, kasutage Kibanat kasutajaliideses pÀringute loomiseks ja vaadake, kuidas kÔne teenuste vahel suunati. JÀlgimis-ID-d on selleks vÀga kasulikud.

Testimise ja silumisega seotud teenused


Algselt ei saanud me tĂ€ielikult aru, kuidas arendatavaid teenuseid siluda. Monoliidiga oli kĂ”ik lihtne; kĂ€itasime seda kohalikul masinal. Alguses prooviti sama teha mikroteenustega, kuid mĂ”nikord on ĂŒhe mikroteenuse tĂ€ielikuks kĂ€ivitamiseks vaja kĂ€ivitada mitu teist ja see on ebamugav. MĂ”istsime, et peame ĂŒle minema mudelile, kus jĂ€tame kohalikku masinasse ainult need teenuse vĂ”i teenused, mida tahame siluda. ÜlejÀÀnud teenuseid kasutatakse serveritest, mis vastavad konfiguratsioonile prod. PĂ€rast silumist vĂ€ljastatakse testimise ajal iga ĂŒlesande jaoks testserverile ainult muudetud teenused. Seega testitakse lahendust sellisel kujul, nagu see tulevikus tootmisse ilmub.

On servereid, mis kÀitavad ainult teenuste tootmisversioone. Neid servereid on vaja vahejuhtumite korral, tarnimise kontrollimiseks enne juurutamist ja sisekoolituseks.

Oleme lisanud automaatse testimisprotsessi, kasutades populaarset Specflow teeki. Testid kĂ€ivituvad automaatselt NUniti abil kohe pĂ€rast Ansible'ist juurutamist. Kui ĂŒlesande katvus on tĂ€isautomaatne, pole kĂ€sitsi testimist vaja. Kuigi mĂ”nikord on siiski vaja tĂ€iendavat kĂ€sitsi testimist. Kasutame Jiras mĂ€rgendeid, et mÀÀrata, milliseid teste konkreetse probleemi korral kĂ€ivitada.

Lisaks on suurenenud vajadus koormustestide jÀrele, varem tehti seda vaid harvadel juhtudel. Testide kÀitamiseks kasutame JMeterit, nende salvestamiseks InfluxDB-d ja protsessigraafikute koostamiseks Grafanat.

Mida me saavutanud oleme?


Esiteks vabanesime mĂ”istest "vabastamine". Möödas on kaks kuud kestnud koletu vĂ€ljalasked, mil see koloss tootmiskeskkonnas kasutusele vĂ”eti, hĂ€irides ajutiselt Ă€riprotsesse. NĂŒĂŒd juurutame teenuseid keskmiselt iga 1,5 pĂ€eva jĂ€rel, rĂŒhmitades need, kuna need kĂ€ivituvad pĂ€rast kinnitamist.

Meie sĂŒsteemis pole surmavaid tĂ”rkeid. Kui anname vĂ€lja veaga mikroteenuse, lĂ€heb sellega seotud funktsionaalsus katki ja kĂ”ik muud funktsionaalsust ei mĂ”juta. See parandab oluliselt kasutajakogemust.

Saame juurutusmustrit juhtida. Vajadusel saate valida teenuste rĂŒhmad ĂŒlejÀÀnud lahendusest eraldi.

Lisaks oleme probleemi oluliselt vĂ€hendanud suure tĂ€iustuste jĂ€rjekorraga. NĂŒĂŒd on meil eraldi tootemeeskonnad, kes töötavad mĂ”ne teenusega iseseisvalt. Scrumi protsess sobib siia juba hĂ€sti. Konkreetsel meeskonnal vĂ”ib olla eraldi tooteomanik, kes mÀÀrab talle ĂŒlesandeid.

KokkuvÔte

  • Mikroteenused sobivad hĂ€sti keerukate sĂŒsteemide lagundamiseks. Selle kĂ€igus hakkame mĂ”istma, mis on meie sĂŒsteemis, millised on piiratud kontekstid, kus on nende piirid. See vĂ”imaldab teil tĂ€iustusi moodulite vahel Ă”igesti jaotada ja vĂ€ltida koodi segadust.
  • Mikroteenused pakuvad organisatsioonilisi eeliseid. Tihti rÀÀgitakse neist vaid kui arhitektuurist, kuid igasugust arhitektuuri on vaja Ă€rivajaduste lahendamiseks, mitte omaette. Seega vĂ”ime öelda, et mikroteenused sobivad hĂ€sti vĂ€ikestes meeskondades probleemide lahendamiseks, arvestades, et Scrum on praegu vĂ€ga populaarne.
  • Eraldamine on iteratiivne protsess. Te ei saa vĂ”tta rakendust ja jagada seda lihtsalt mikroteenusteks. Saadud toode ei ole tĂ”enĂ€oliselt funktsionaalne. Mikroteenuste pĂŒhendamisel on kasulik olemasolev pĂ€rand ĂŒmber kirjutada ehk muuta see meile meeldivaks ning funktsionaalsuse ja kiiruse poolest paremini Ă€rivajadustele vastavaks koodiks.

    VĂ€ike hoiatus: Mikroteenustele ĂŒlemineku kulud on ĂŒsna mĂ€rkimisvÀÀrsed. Üksinda taristuprobleemi lahendamine vĂ”ttis kaua aega. Nii et kui teil on vĂ€ike rakendus, mis ei vaja spetsiifilist skaleerimist, vĂ€lja arvatud juhul, kui teie meeskonna tĂ€helepanu ja aja pĂ€rast vĂ”istleb suur hulk kliente, siis ei pruugi mikroteenused olla need, mida te tĂ€na vajate. See on ĂŒsna kallis. Kui alustada protsessi mikroteenustega, siis on kulud esialgu suuremad kui sama projektiga alustamisel monoliidi arendamisega.

    PS Emotsionaalsem lugu (ja nagu sulle isiklikult) - vastavalt link.
    Siin on aruande tÀisversioon.

Allikas: www.habr.com

Ostke DDoS-kaitsega saitide jaoks usaldusvÀÀrne hostimine, VPS VDS-serverid đŸ”„ Osta usaldusvÀÀrne veebimajutus DDoS-kaitsega, VPS VDS serverid | ProHoster