
Sa më shpejt zhvillohet procesi i zhvillimit, aq më shpejt rritet kompania teknologjike.
PĂ«r fat tĂ« keq, aplikacionet moderne punojnĂ« kundĂ«r nesh â sistemet tona duhet tĂ« pĂ«rditĂ«sohen nĂ« kohĂ« reale dhe nĂ« tĂ« njĂ«jtĂ«n kohĂ« tĂ« mos shqetĂ«sojnĂ« asnjĂ« dhe tĂ« mos sjellin ndĂ«rprerje dhe pushime. Zhvillimi nĂ« kĂ«to sisteme bĂ«het njĂ« detyrĂ« e vĂ«shtirĂ« dhe kĂ«rkon pipeline tĂ« komplikuara tĂ« dĂ«rgesĂ«s continue edhe nĂ« ekipet e vogla.
Këto pipeline zakonisht kanë një përdorim të ngushtë, punojnë ngadalë dhe nuk janë të besueshëm. Zhvilluesit duhet të krijojnë ato manualisht fillimisht dhe pastaj t'i menaxhojnë ato, dhe kompanitë shpesh punësojnë ekipe të tëra DevOps për këtë.
ShpejtĂ«sia e kĂ«tyre pipeline-ve pĂ«rcakton shpejtĂ«sinĂ« e zhvillimit. NĂ« ekipet mĂ« tĂ« mira, zhvillimi zgjat 5â10 minuta, por zakonisht gjithçka bĂ«het shumĂ« mĂ« ngadalĂ« dhe pĂ«r njĂ« zhvillim nevojiten disa orĂ«.
NĂ« Dark, kjo zĂ« 50 ms. PesĂ«dhjetĂ«. Milisekonda. Dark â , e krijuar posaçërisht pĂ«r dĂ«rgesĂ«n continue, dhe tĂ« gjitha aspektet e Dark, pĂ«rfshirĂ« vetĂ« gjuhĂ«n, janĂ« ndĂ«rtuar me njĂ« sy pĂ«r zhvillim tĂ« sigurt momental.
Pse janë kaq të ngadalta pipeline-t e dërgesës continue?
Supozoni se kemi një aplikacion web në Python dhe ne kemi krijuar një pipeline të shkëlqyer dhe modern të dërgesës continue. Për një zhvillues që është i angazhuar në këtë projekt çdo ditë, zhvillimi i një ndryshimi të vogël do të dukej kështu:
Bërja e ndryshimeve
- Krijimi i një dege të re në git
- Bërja e ndryshimeve përmes ndërruesit të funksionit
- Testimi modular për të kontrolluar ndryshimet me dhe pa ndërruesin e funksionit
Kërkesa për bashkim
- Komitimi i ndryshimeve
- Dërgimi i ndryshimeve në repo të largët në github
- Kërkesa për bashkim
- Ndërtimi CI kryhet automatikisht në sfond
- Rishikimi i kodit
- Disa rishikime shtesë, nëse është e nevojshme
- Bashkimi i ndryshimeve me master-in git.
CI kryhet në master
- Instalimi i varësive front-end përmes npm
- Ndërtimi dhe optimizimi i burimeve HTML+CSS+JS
- Ekzekutimi i testimeve modulare dhe funksionale në front-end
- Instalimi i varësive Python nga PyPI
- Ekzekutimi i testimeve modulare dhe funksionale në backend
- Testimi i integrimit në të dy skajet
- Dërgimi i burimeve të front-end në CDN
- Ndërtimi i një kontejneri për programin Python
- Dërgimi i kontejnerit në regjistër
- Përditësimi i manifestit Kubernetes
Zëvendësimi i kodit të vjetër me të riun
- Kubernetes aktivizon disa instanca të kontejnerit të ri
- Kubernetes pret që instancat të bëhen funksionale
- Kubernetes shton instancat në balancuesin e ngarkesës HTTP
- Kubernetes pret derisa instancat e vjetra të ndalen së përdoruri
- Kubernetes ndalon instancat e vjetra
- Kubernetes përsërit këto operacione derisa instancat e reja të zëvendësojnë të gjitha të vjetrat
Aktivizimi i një kalimi të ri të funksionit
- Kodi i ri aktivizohet vetëm për veten e tij, për t'u siguruar që gjithçka është në rregull
- Kodi i ri aktivizohet për 10% të përdoruesve, duke monitoring-uar metrikat operuese dhe ato të biznesit
- Kodi i ri aktivizohet për 50% të përdoruesve, duke monitoring-uar metrikat operuese dhe ato të biznesit
- Kodi i ri aktivizohet për 100% të përdoruesve, duke monitoring-uar metrikat operuese dhe ato të biznesit
- Në fund, ju përsërisni të gjithë procedurën për të hequr kodin e vjetër dhe kalimin
Procesi varet nga mjetet, gjuha dhe përdorimi i arkitekturave të orientuara nga shërbimi, por në përgjithësi duket kështu. Nuk i përmenda shpërndarjet me migrazhimin e bazës së të dhënave, sepse për këtë nevojitet planifikim i kujdesshëm, por më poshtë do të flas si e trajton Dark këtë.
Ka shumë komponentë këtu, dhe shumica e tyre mund të ngadalësojnë, të dështojnë, të shkaktojnë konkurrencë të përkohshme ose të prishin sistemin e punës.
Dhe pasi këto pipeline zakonisht janë krijuar për raste të veçanta, është e vështirë të mbështetesh në to. Shumë herë ka ditë kur kodi nuk mund të shpërndahet, sepse ka probleme në Dockerfile, një nga dhjetëra shërbimeve ka dështuar, ose specialisti i nevojshëm është në pushim.
Më keq akoma, shumë nga këto hapa nuk bëjnë absolutisht asgjë të dobishme. Ato ishin të nevojshme më parë, kur shpërndanim kodin direkt për përdoruesit, por tani kemi kalime për kodin e ri, dhe këto procese janë ndarë. Si rezultat, hapi në të cilin shpërndahet kodi (i vjetri zëvendësohet me të riun), tani është thjesht një rrezik i panevojshëm.
Sigurisht, ky është një pipeline shumë i menduar. Ekipa që e krijoi atë nuk kursyeu as kohë as para për shpërndarjen e shpejtë. Zakonisht, pipeline-et e shpërndarjes janë shumë më të ngadalta dhe të pasigurt.
Implementimi i shpërndarjes së vazhdueshme në Dark
Furnizimi i vazhdueshëm është kaq i rëndësishëm për Dark, sa që nga fillimi e kemi synuar një kohë më pak se një sekondë. Ne kemi shqyrtuar të gjitha hapat e pipeline-it për të hequr çdo të panevojshme dhe e kemi përsosur atë që mbeti. Këtu është se si ne heqëm hapat.
Jesse Frazelle () shpiku fjalën e re deployless (pa nevojë për shpërndarje) në konferencën Future of Software Development në Reykjavik
Ne menjëherë vendosëm që Dark do të bazohej në konceptin e 'deployless' (faleminderit për neologjinë). Deployless do të thotë që cili do kod shpërndahet menjëherë dhe është gati për përdorim në prodhim. Sigurisht, nuk do të kalojmë as një kod të dështuar ose të paplotë (parimet e sigurisë do t'i përshkruaj më poshtë).
GjatĂ« demonstratĂ«s sĂ« Dark, shpesh na pyesnin se si arritĂ«m tĂ« shpejtonim shpĂ«rndarjen kaq shumĂ«. NjĂ« pyetje e çuditshme. NjerĂ«zit mendojnĂ« se kemi shpikur njĂ« supĂ«rteknologji qĂ« krahason kodin, e kompilon, e paketĂ«n nĂ« njĂ« konteiner, nis njĂ« makinĂ« virtuale, nis konteinerit nga e ftohtĂ« dhe gjithçka tjetĂ«r, pĂ«r 50 ms. ĂshtĂ« e vĂ«shtirĂ« ta besosh. Por ne krijuam njĂ« motor tĂ« veçantĂ« shpĂ«rndarjeje, i cili nuk ka nevojĂ« pĂ«r tĂ« gjithĂ« kĂ«to.
Dark nis interpretorĂ«t nĂ« cloud. Supozoni se po shkruani kod nĂ« njĂ« funksion ose trajtues HTTP ose ngjarjesh. Ne dĂ«rgojmĂ« dallimin nĂ« pemĂ«n sintetike abstrakte (implementimin e kodit qĂ« pĂ«rdor brenda editori tonĂ« dhe serverĂ«ve) nĂ« serverĂ«t tanĂ«, dhe mĂ« pas e ekzekutojmĂ« kĂ«tĂ« kod kur arrijnĂ« kĂ«rkesat. Pra, shpĂ«rndarja duket thjesht si njĂ« regjistrim modest nĂ« njĂ« bazĂ« tĂ« dhĂ«nash â momentale dhe elementare. ShpĂ«rndarja ndodh kaq shpejt, sepse pĂ«rfshin minimumin e nevojshĂ«m.
Në të ardhmen, ne kemi në plan të bëjmë nga Dark një kompilator infrastrukture që do të krijosh dhe nisësh infrastrukturën ideale për performancë të lartë dhe besueshmëri të aplikacioneve. Shpërndarja momentale, natyrisht, nuk do të largohet.
Shpërndarje e sigurt
Editor i strukturuar
Kodi në Dark shkruhet në redaktorin Dark. Editor i strukturuar nuk lejon gabime sintaksore. Në thelb, Dark nuk ka as një analizues. Ndërsa ju shkruani tekstin, ne punojmë direkt me pemën sintetike abstrakte (AST), sikurse , , , dhe .
Cili do kod i papërfunduar në Dark ka një semantikë të pranueshme ekzekutimi, disi si Për shembull, nëse ndryshoni thirrjen e funksionit, ne ruajmë funksionin e vjetër derisa i riu të bëhet i përshtatshëm.
Ădo program nĂ« Dark ka kuptimin e tij, prandaj kodi i papĂ«rfunduar nuk pengon atĂ« tĂ« pĂ«rfunduar tĂ« punojĂ«.
Mënyrat e redaktimit
Ju shkruani kod në Dark në dy raste. I pari: shkruani kod të ri dhe jeni përdoruesi i vetëm. Për shembull, ai është në REPL dhe përdoruesit e tjerë kurrë nuk do të kenë qasje në të, ose është një rrugë e re HTTP, të cilën nuk e referoni askund. Këtu mund të punoni pa masa paraprake, dhe tani jeni përafërsisht kështu duke punuar në ambientin e zhvillimit.
Situata e dytë: kodi tashmë është duke u përdorur. Nëse trafiku kalon përmes kodit (funksione, trajtues ngjarjesh, baza të dhënash, etj.), është e nevojshme të jeni të kujdesshëm. Për këtë, ne bllokojmë të gjithë kodin e përdorur dhe kërkojmë që të përdoren mjete më strukturore për redaktimin e tij. Më poshtë do t'ju tregoj për mjetet strukturore: kaluesit e funksioneve për trajtuesit HTTP dhe ngjarjeve, një platformë e fuqishme migrimi për bazat e dhënash dhe një metodë të re për menaxhimin e versioneve për funksione dhe lloje.
Kaluesit e funksioneve
Një nga mënyrat në Dark është të zgjidhni disa probleme me një zgjidhje. Kaluesit e funksioneve kryejnë shumë detyra të ndryshme: zëvendësimi i ambientit lokal të zhvillimit, degët git, vendosja e kodit dhe, natyrisht, lëshimi tradicional i ngadalshëm dhe i kontrolluar i kodit të ri.
Krijimi dhe vendosja e kaluesit të funksionit bëhet në redaktorin tonë në një operacion. Ai krijon një hapësirë të zbrazët për kodin e ri dhe ofron elemente kontrolli për qasjen në kodin e vjetër dhe të ri, si dhe butona dhe komanda për një kalim gradual në kodin e ri ose për përjashtimin e tij.
Kaluesit e funksioneve janë të integruar në gjuhën Dark, dhe madje kaluesit e papërfunduar kryejnë detyrën e tyre - nëse kushti në kalues nuk përmbushet, do të ekzekutohet kodi i vjetër i bllokuar.
Mjedisi i zhvillimit
Ndërruesit e funksioneve zëvendësojnë ambientin lokal të zhvillimit. Sot, ekipeve u është e vështirë të sigurojnë që gjithkush të përdorë versione të njëjta të mjeteve dhe bibliotekeve (mjetet e formatimit të kodit, linters, menaxherët e paketave, kompilerët, preprocessors, mjetet e testimit etj.) Me Dark nuk është nevoja të instaloni varësi lokalisht, të menaxhoni instalimin lokal të Docker ose të merrni masa të tjera për të siguruar të paktën një farë barazie midis ambientit të zhvillimit dhe prodhimit. , ne as nuk do të pretendojmë se po e ndjekim atë.
Në vend që të krijojmë një ambient lokal të klonuar, ndërruesit në Dark krijojnë një sand të re në prodhim, e cila zëvendëson ambientin e zhvillimit. Në të ardhmen, ne gjithashtu planifikojmë të krijojmë një sand për pjesë të tjera të aplikacionit (p.sh. klonat momentale të bazës së të dhënave), edhe pse për momentin kjo nuk duket kaq e rëndësishme.
Degët dhe shpërndarjet
Aktualisht ka disa mënyra për të futur kod të ri në sisteme: degët git, faza e shpërndarjes dhe ndërruesit e funksioneve. Ato zgjidhin një problem në pjesë të ndryshme të procesit të punës: git - në fazat para shpërndarjes, shpërndarja - në momentin e kalimit nga kodi i vjetër në të riun, dhe ndërruesit e funksioneve - për një lëshim të kontrolluar të kodit të ri.
Mënyra më efektive është ndërruesit e funksioneve (në të njëjtën kohë, më të thjeshtë për t'u kuptuar dhe përdorur). Me ta mund të heqim dorë plotësisht nga dy metodat e tjera. Sidomos e dobishme është të fshijmë fazën e shpërndarjes - nëse ne gjithësesi po përdorim ndërruesit e funksioneve për të aktivizuar kodin, atëherë hapi i kalimit të serverëve në kodin e ri krijon vetëm rreziqe të tepërta.
Git është e vështirë për t'u përdorur, sidomos për fillestarët, dhe kjo e kufizon shumë, por ndihmon me degët e tij të dobishme. Ne kemi sheshuar shumë nga disavantazhet e git. Dark redaktohet në kohë reale dhe ofron mundësinë e bashkëpunimit në stilin e Dokumenteve të Google, kështu që nuk ka nevojë të dërgoni kodin dhe të bëni refaktorizim dhe bashkime më rrallë.
Funksionet e kalimit janë thelbësor për implementimin e sigurt. Së bashku me deploy-et e menjëhershme, ato lejojnë testimin e shpejtë të koncepteve në pjesë të vogla me rrezik të ulët, në vend që të bëni një ndryshim të madh që mund të rrëzojë sistemin.
Versionimi
Për të ndryshuar funksionet dhe llojet, ne përdorim versionimin. Nëse dëshironi të ndryshoni një funksion, Dark krijon një version të ri të këtij funksioni. Më pas mund ta thërrisni këtë version përmes një kalimi në trajtuesin HTTP ose ngjarjeve. (Nëse ky është një funksion thellë në grafikun e thirrjeve, një version i ri krijohet për secilin funksion gjatë procesit. Mund të dukej se është tejet, por funksionet nuk ngatërrohen nëse nuk i përdorni, kështu që madje nuk do ta vini re.)
Për të njëjtat arsye, ne versionojmë llojet. Ne kemi folur në detaje për sistemin tonë të llojeve. .
Falë versionimit të funksioneve dhe llojeve, mund të bëni ndryshime në aplikacion gradualisht. Mund të kontrolloni që secili trajtues funksionon me versionin e ri pa qenë e nevojshme të bëni të gjitha ndryshimet në aplikacione menjëherë (por ne kemi mjete për ta bërë këtë shpejt nëse dëshironi).
Kjo është shumë më e sigurt se sa implementimi i gjithçkaje njëkohësisht, siç ndodh tani.
Versionet e reja të paketave dhe biblioteka standarde
Kur përditësoni një paketë në Dark, ne nuk zëvendësojmë menjëherë përdorimin e secilit funksion ose tip në të gjithë bazën e kodit. Kjo nuk është e sigurt. Kodi vazhdon të përdorë versionin e njëjtë që ka përdorur, ndërsa ju përditësoni përdorimin e funksioneve dhe llojeve në versionin e ri për çdo rast të veçantë me ndihmën e kalimeve.
Screenshot i një pjese të procesit automatik në Dark, duke treguar dy versione të funksionit Dict::get. Dict::get_v0 kthente tipin Any (të cilin ne po e heqim), ndërsa Dict::get_v1 kthente tipin Option.
Ne shpesh ofrojmë një funksion të ri në bibliotekën standarde dhe përjashtojmë versionet e vjetra. Përdoruesit me versione të vjetra në kod do të ruajnë qasje tek ato, por përdoruesit e rinj nuk do të jenë në gjendje t'i marrin ato. Ne po planifikojmë të ofrojmë mjete për të transferuar përdoruesit nga versionet e vjetra në të rejat me një hap, gjithashtu duke përdorur kalime funksionesh.
Dark ofron edhe një mundësi unike: përderisa ne ekzekutojmë kodin tuaj të punës, ne mund ta testojmë vetë versionet e reja duke krahasuar daljet për kërkesat e reja dhe ato të vjetra, për t'ju informuar mbi ndryshimet. Si rezultat, azhurnimi i pakove, i cili shpesh kryhet në errësirë (ose kërkon testim të kujdesshëm për siguri), paraqet shumë më pak rreziqe dhe mund të ndodhë automatikisht.
Versionet e reja të Dark
Kalimi nga Python 2 në Python 3 zgjati një dekadë dhe akoma mbetet një problem. Duke pasur parasysh se ne po e krijojmë Dark për shpërndarje të vazhdueshme, duhet të kemi parasysh këto ndryshime të gjuhës.
Kur ne bëjmë ndryshime të vogla në gjuhë, ne krijojmë një version të ri të Dark. Kodi i vjetër mbetet në versionin e vjetër të Dark, ndërsa kodi i ri përdoret në versionin e ri. Për të kaluar në versionin e ri të Dark, mund të përdoren kaluesit ose versionet e funksioneve.
Kjo është veçanërisht e dobishme, duke pasur parasysh se Dark u shfaq shumë kohët e fundit. Shumë ndryshime në gjuhë ose bibliotekë mund të rezultojnë të dështojnë. Versionimi gradual i gjuhës na lejon të bëjmë azhurnime të vogla, domethënë ne mund të mos ngutemi dhe të shtyjmë shumë vendime mbi gjuhën derisa të kemi më shumë përdorues, që do të thotë më shumë informacion.
Migrimi i bazave të të dhënave
Për një migrim të sigurt të bazës së të dhënave, ekziston :
- Rikopjimi i kodit për të mbështetur formate të reja dhe të vjetra
- Transformimi i të gjitha të dhënave në formatin e ri
- Heqja e aksesit të vjetër në të dhëna
Si rezultat, migrazione e bazës së të dhënave vonohet dhe kërkon shumë burime. Dhe ne grumbullojmë skema të vjetra, sepse madje edhe detyra të thjeshta, si rregullimi i emrit të tabelës ose kolonës, nuk ia vlen përpjekjet e shpenzuara.
Dark ka një platformë efektive për migrimin e bazave të të dhënave, e cila (shpresojmë) do ta thjeshtojë procesin aq shumë sa do të ndaloni së pasuri frikë për të. Të gjitha depozitat e të dhënave në Dark (depozita çiftësh «çelës-vlerë» ose tabela të qëndrueshme) kanë një tip. Për të transferuar një depozitë të dhënash, thjesht i jepni asaj një tip të ri dhe funksion të rikthimit dhe rikthimit për të transformuar vlerat midis dy tipeve.
Qasja në magazinat e të dhënave në Dark bëhet përmes emrave të variablave të versionuar. Për shembull, magazina e të dhënave Users fillimisht do të quhet Users-v0. Kur krijohet një version i ri me një lloj tjetër, emri ndryshon në Users-v1. Nëse të dhënat ruhen përmes Users-v0 dhe ju i qaseni ato përmes Users-v1, aplikohet funksioni i rikthimit. Nëse të dhënat ruhen përmes Users-v1 dhe ju i qaseni ato përmes Users-v0, aplikohet funksioni i kthimit pas.
Ekrani i migrimit të bazës së të dhënave me emrat e fushave të vjetra të bazës së të dhënave, shprehjet e rikthimit dhe kthimit pas dhe udhëzimet për aktivizimin e migrimit.
Përdorni kaluesit e funksioneve për t'i udhëzuar thirrjet nga Users-v0 në versionin Users-v1. Kjo mund të bëhet për një trajtim HTTP në një kohë, për të ulur rreziqet, dhe kaluesit punojnë për përdorues të veçantë, në mënyrë që të mund të kontrolloni se çdo gjë funksionon siç pritej. Kur të mos ketë më përdorues në Users-v0, Dark do të konvertojë të dhënat e mbetura në sfond nga formati i vjetër në atë të ri. Ju nuk do ta vini re këtë.
Testimi
Dark është dhe vlera të pandryshueshme, prandaj sipërfaqja e testimit është dukshëm më e vogël krahasuar me gjuhët objekt-orientuese me tipizim dinamik. Por ende është e nevojshme të bëhet testimi.
Në Dark, redaktori automatikisht ekzekuton testin modular në sfond për kodin që po redaktohet dhe automatikisht ekzekuton këto teste për të gjitha kaluesit e funksioneve. Në të ardhmen, dëshirojmë që përmes tipave statikë të ekzekutojmë automatikisht fuzzing të kodit për të gjetur gabimet.
Për më tepër, Dark ekzekuton infrastrukturën tuaj në prodhim, e cila hap mundësi të reja. Ne automatikisht ruajmë kërkesat HTTP në infrastrukturën Dark (deri tani ruajmë të gjitha kërkesat, por më vonë duam të kalojmë në sampling). Ne i testojmë ato me kodin e ri dhe kryejmë teste modulare, dhe nëse dëshironi, mund të shndërroni lehtësisht kërkesat interesante në teste modulare.
ĂfarĂ« ne hoqĂ«m
Duke qenë se nuk kemi shpërndarje, por kemi kaluesit e funksioneve, rreth 60% e pipeline-it të shpërndarjes mbetet jashtë. Nuk kemi nevojë për degë git ose kërkesa për tërheqje, ndërtimin e burimeve prapa dhe kontejnerëve, dërgimin e burimeve dhe kontejnerëve në regjistra ose hapa shpërndarjeje në Kubernetes.
Krahasimi i pipeline-it tradicional të shpërndarjes së vazhdueshme (majtas) dhe shpërndarja e vazhdueshme Dark (djathtas). Në Dark, shpërndarja përbëhet nga 6 hapa dhe një cikël, ndërsa versioni tradicional përfshin 35 hapa dhe 3 cikle.
Në Dark, ka vetëm 6 hapa dhe 1 cikël (hapat që përsëriten disa herë) në shpërndarje, ndërsa pipeline-i modern i shpërndarjes së vazhdueshme përbëhet nga 35 hapa dhe 3 cikle. Në Dark, testet ekzekutohen automatikisht dhe nuk e shihni; varësitë instalohet automatikisht; gjithçka që lidhet me git ose Github nuk është më e nevojshme; nuk nevojitet të ndodhë ndërtimi, testimi dhe dërgimi i kontejnerëve Docker; shpërndarja në Kubernetes nuk është më e nevojshme.
Edhe hapat e mbetur në Dark janë bërë më të lehta. Meqenëse ndërruesit e funksioneve mund të menaxhohen me një veprim, nuk është më e nevojshme të kaloni përmes të gjithë pipeline-it të shpërndarjes për të hequr kodin e vjetër.
Ne e kemi thjeshtuar sa më shumë që të jetë e mundur shpërndarjen e kodit, duke reduktuar kohën dhe rreziqet e shpërndarjes së vazhdueshme. Po ashtu, ne e kemi thjeshtuar gjithashtu azhurnimin e paketave, migrimet e bazës së të dhënave, testimin, menaxhimin e versioneve, instalimin e varësive, barazinë midis mjediseve të zhvillimit dhe prodhimit dhe azhurnime të shpejta dhe të sigurta të versioneve të gjuhës.
Unë po përgjigjem në pyetje për këtë në .
Për të mësuar më shumë rreth pajisjes Dark, lexoni , (ose në ) ose . Nëse po shkoni në StrangeLoop në shtator, .
Burimi: habr.com
