Kuidas Dark käivitab koodi 50 ms jooksul

Kuidas Dark käivitab koodi 50 ms jooksul

Mida kiiremini arenduse protsess kulgeb, seda kiiremini areneb tehnoloogiaettevõte.

Kahjuks töötavad tänapäeva rakendused meie vastu – meie süsteemid peavad uuendama reaalajas, samas kedagi segamata ja katkestusi tekitamata. Selliste süsteemide kasutuselevõtt muutub keeruliseks ülesandeks ning nõuab isegi väikestes meeskondades keerukaid pideva tarnimise torustikke.

Need torustikud on tavaliselt kitsase kasutusalaga, aeglased ja ebausaldusväärsed. Arendajad peavad need esmalt käsitsi looma ja seejärel hallama, mistõttu paljud ettevõtted palkavad selleks tervet DevOps'i meeskonda.

Nende torustike kiirus määrab arenduse kiirus. Parimatel meeskondadel võtab kasutusevõtt aega 5–10 minutit, kuid tavaliselt kestab see palju kauem ja ühe kasutusevõtu jaoks kulub mitu tundi.

Darkis kulub sellele 50 ms. Viiskümmend. Millisekundit.. Dark on kompleksne lahendus koos programmeerimiskeele, redigeerija ja infrastruktuuriga., mis valmistati pidevaks tarnegra, ning kõik aspektid Darkist, sealhulgas keel, on üles ehitatud turvalise ja kohese juurutamise silmas pidades.

Miks on pideva tarnimise torujuhtmed nii aeglased?

Oletame, et meil on veebirakendus Pythonis ja me oleme juba loonud suurepärase ja kaasaegse pideva tarnimise torujuhtme. Arendaja, kes on iga päev selle projektiga hõivatud, peab üht väikest muudatust juurutama nii:

Muudatuste tegemine

  • Uue haru loomine git'is
  • Muudatuste tegemine funktsioonide lülitamise abil
  • Moodulitestimine muudatuste kontrollimiseks funktsioonide lülitamisega ja ilma

Pull-request

  • Muudatuste committimine
  • Muudatuste saatmine kaugrepository'sse GitHubis
  • Pull-request
  • CI kogumise automaatne käivitamine taustal
  • Koodiarvustus
  • Veel mõned arvustused, kui vajalik
  • Muudatuste sulandumine git'i masteriga.

CI töötab masteril

  • Frontend sõltuvuste installimine npm-i kaudu
  • HTML+CSS+JS ressursside kogumine ja optimeerimine
  • Moodulite ja funktsionaalsete testide käitamine frontendis
  • Python sõltuvuste installimine PyPist
  • Moodulite ja funktsionaalsete testide käitamine backend'is
  • Integratsiooni testimine mõlemal lõpus
  • Frontend'i ressursside saatmine CDN-i
  • Python programmi konteineri koostamine
  • Konteineri saatmine registrisse
  • Kubernetes'i manifesti värskendamine

Vanade koodide asendamine uutega

  • Kubernetes käivitab mitu uue konteineri instantsi
  • Kubernetes ootab, et instantsid muutuksid töövõimeliseks
  • Kubernetes lisab instantsid HTTP koormuse tasakaalustajasse
  • Kubernetes ootab, kuni vanad instantsid lõpetavad kasutamise
  • Kubernetes peatab vanad instantsid
  • Kubernetes kordab neid toiminguid, kuni uued instantsid asendavad kõik vanad

Uue funktsiooni lüliti sisse lülitamine

  • Uus kood lülitub sisse ainult enda jaoks, et veenduda, et kõik on korras
  • Uus kood lülitub sisse 10% kasutajatest, jälgitakse töö- ja äri-metreid
  • Uus kood lülitub sisse 50% kasutajatest, jälgitakse töö- ja äri-metreid
  • Uus kood lülitub sisse 100% kasutajatest, jälgitakse töö- ja äri-metreid
  • Lõpuks kordate kogu protseduuri, et eemaldada vana kood ja lüliti

Protsess sõltub tööriistadest, keelest ja teenusele suunatud arhitektuuride kasutamisest, kuid üldjoontes näeb see välja nii. Ma ei maininud andmebaaside migratsiooniga seotud juurutamisi, sest see nõuab põhjalikku planeerimist, kuid allpool räägin, kuidas sellega Dark tegeleb.

Siin on palju komponente, ja paljud neist võivad kergesti aeglustuda, rike toimuda, põhjustada ajutisi konflikte või süsteemi kokku kukkuda.

Kuna need torujuhtmed on peaaegu alati loodud konkreetse juhtumi jaoks, on neile raske toetuda. Paljudel võivad olla päevad, mil koodi ei õnnestu rakendada, sest Dockerfile'is on probleeme, ühes kümnetest teenustest on juhtunud rike või vajalik spetsialist on puhkusel.

Vaatamata sellele, et paljud neist sammudest ei tee üldse midagi kasulikku. Need olid vajalikud varem, kui juurutasime koodi otse kasutajatele, kuid nüüd on meil uute koodide jaoks lülitid ja need protsessid on jagunenud. Tulemuseks on see, et samm, mil kood juurutatakse (vana asendatakse uuega), on nüüd lihtsalt liigne risk.

Muidugi, see on väga läbimõeldud töövoog. Meeskond, kes selle lõi, ei säästnud aega ja raha kiiruselt juurutamiseks. Tavalised juurutustöövood on tavaliselt palju aeglasemad ja usaldusväärsemad.

Pideva tarnimise rakendamine Darkis

Pidev tarnimine on Darkile nii oluline, et sihtisime algusest peale alla sekundi aega. Vaatasime kõiki töövoo samme, et eemaldada kõik üleliigne, ja viimistlesime ülejäänud. Nii me samme eemaldame.

Jessie Frazelle (Jessie Frazelle) leiutas uue sõna deployless (juurutamata) Future of Software Development konverentsil Reykjavikis.

Otsustasime kohe, et Dark põhineb mõiste „deployless” (aitäh Jessie Frazelle uue sõna eest). Deployless tähendab, et iga kood juurutatakse koheselt ja on tootmises kasutamiseks valmis. Loomulikult ei jäta me tähelepanuta defektset või mittetäielikku koodi (turvaperioodid, millest kirjutan allpool).

Darki demonstreerimise ajal küsiti meilt tihti, kuidas me suudame nii kiiresti seadistada. See on veider küsimus. Inimesed arvavad ilmselt, et oleme välja mõelnud mingi supertehnoloogia, mis võrdleb koodi, kompileerib selle, pakib konteinerisse, käivitab virtuaalmasina, tõukab konteineri külmalt käima ja seda kõike 50 ms jooksul. See on tõenäoliselt võimatu. Kuid oleme loonud spetsiaalse seadistamismootor, millele pole seda kõike vaja.

Dark käivitab tõlgendajad pilves. Oletame, et kirjutate koodi funktsioonis või HTTP või sündmuste töötlejas. Saatma diffi abstraktse süntakspuu (koodi teostus, mida meie redaktor ja serverid sisemiselt kasutavad) meie serveritesse ning seejärel käivitame selle koodi, kui saabuvad päringud. Seetõttu näeb seadistamine välja nagu tagasihoidlik kirje andmebaasis — hetkeline ja elementaarne. Seadistamine toimub nii kiiresti, kuna see sisaldab kõige vähem.

Tulevikus plaanime Darkist luua infrastruktuuri koostaja, mis suudab luua ja käivitada ideaalse infrastruktuuri rakenduste kõrge jõudluse ja töökindluse tagamiseks. Kohene juurutamine jääb kindlasti alles.

Turvaline juurutamine

Struktuurne redaktor

Darki kood kirjutatakse Darki redaktoris. Struktuurne redaktor ei luba süntaksivigu. Tegelikult ei ole Darkis isegi analüsaatorit. Kui te tekstis sisestate, töötame me otse abstraktse süntaksipuuga (AST), näiteks Paredit, Sketch-n-Sketch, Tofu, Prune ja MPS.

Iga lõpetamata koodi puhul Darkis on lubatud semantika täitmiseks, umbes nagu typed holes Hazelis. Näiteks, kui muudate funktsiooni kutsumist, hoiame vana funktsiooni, kuni uus on sobiv.

Igal programmi Darkis on oma tähendus, seega ei segada lõpetamata kood ka lõpetatud tööd.

Redigeerimisrežiimid

Te kirjutate koodi Darkis kahes olukorras. Esimene: kirjutate uut koodi ja olete ainus kasutaja. Näiteks on see REPL-is, ja teised kasutajad ei pääse sellele kunagi ligi, või see on uus HTTP marsruut, millele te ei viita. Siin saab töötada ilma eriliste ettevaatusabinõudeta, ja praegu te töötate täpselt nii arenduskeskkonnas.

Teine olukord: kood on juba kasutuses. Kui koodi kaudu läbib liiklus (funktsioonid, sündmuste töötlejad, andmebaasid jne), tuleb olla ettevaatlik. Selleks blokeerime kogu kasutuses oleva koodi ja nõuame struktureeritud tööriistade kasutamist selle redigeerimiseks. Struktureeritud tööriistadest räägin allpool: funktsioonide lülitid HTTP töötlejatele ja sündmustele, võimas andmebaaside migratsiooniplatvorm ning uus versioonihalduse meetod funktsioonide ja tüüpide jaoks.

Funktsioonide lülitid

Üks viis liigse keerukuse vähendamiseks Darkis on võimalik lahendada mitmeid probleeme ühe lahendusega. Funktsioonide lülitid täidavad palju erinevaid ülesandeid: lokaalsete arenduskeskkondade asendamine, git-haarakohad, koodi juurutamine ja muidugi traditsiooniline aeglane ja kontrollitud uue koodi väljaandmine.

Funktsionaalsuse lüliti loomine ja juurutamine toimub meie redigeerijas ühe toiminguna. See loob uue koodi jaoks tühja ruumi ja pakub juurdepääsueeliseid vanale ja uuele koodile, samuti nuppe ja käske uuele koodile järkjärguliseks üleminekuks või selle välja jätmiseks.

Funktsioonide lülitid on sisse ehitatud Darki keelde ja isegi lõpetamata lülitid täidavad oma ülesannet — kui lüliti tingimus ei ole täidetud, täidetakse vana blokeeritud kood.

Arenduskeskkond

Funktsioonide lülitid asendavad kohalikku arenduskeskkonda. Täna on meeskondadel keeruline jälgida, et kõik kasutaksid samu tööriistade ja raamatukogude versioone (koodivormindustooted, linterid, paketihaldurid, kompilaatorid, eeltöötlejad, testimistooted jne). Darki puhul pole vaja sõltuvusi kohalikult installida, hallata kohalikku Docker'i installatsiooni või võtta muid meetmeid, et tagada vähemalt mingi sarnasus arenduskeskkonna ja tootmise vahel. Arvestades, et selline sarnasus on ikkagi võimatu,, me isegi ei teeselda, et püüame selle poole.

Selle asemel, et luua kloonitud kohalikku keskkonda, loovad Darki lülitid uue liivakasti tootmises, mis asendab arenduskeskkonna. Tulevikus plaanime luua liivakast ka teiste rakenduse osade jaoks (näiteksandmebaasi hetkekloonid), kuigi praegu ei tundu see nii oluline.

Harud ja väljatõmbamised

Praegu on mitu võimalust uut koodi süsteemidesse sisestada: git harud, juurutamisetapid ja funktsioonilülitid. Need lahendavad sama probleemi erinevates tööprotsessi osades: git - enne juurutamist etappides, juurutamine - vana koodist uue koodi ülemineku hetkel ning funktsioonilülitid - uue koodi kontrollitud väljastamiseks.

Tõhusaim viis on funktsioonilülitid (samuti kõige lihtsam mõista ja kasutada). Nende abil saab täielikult loobuda teistest kahest meetodist. Eelkõige on kasulik juurutamist eemaldada - kui me ikkagi kasutame funktsioonilüliteid koodi lubamiseks, siis serverite ülemineku etapp uuele koodile tekitab ainult täiendavaid riske.

Giti kasutamine on keeruline, eriti algajatele, ja see piirab oma võimalusi, kuid tal on mugavad harud. Oleme tasandanud paljusid giti puudusi. Dark redigeeritakse reaalajas ja võimaldab koostööd Google Docs stiilis, et ei peaks koodi saatma ja saaks harvemini rebasi ja ühte liita.

Funktsioonide vahetused on turvalise juurutamise aluseks. Koos kiirete juurutustega võimaldavad need kiiresti katsetada kontseptsioone väikeste madala riskiga fragmentide kaudu, selle asemel, et rakendada ühte suurt muudatust, mis võib süsteemi kukutada.

Versioonimine

Funktsioonide ja tüüpide muutmiseks kasutame versioonimist. Kui soovite funktsiooni muuta, loob Dark selle funktsiooni jaoks uue versiooni. Seejärel saate seda versiooni kutsuda välja vahetaja kaudu HTTP või sündmuste käsitlejasse. (Kui see funktsioon on sügaval kutsumisgraafikus, luuakse iga korda uus versioon igast funktsioonist. See võib tunduda liialt, kuid funktsioonid ei sega üksteist, kui te neid ei kasuta, seega ei pruugi te seda isegi märgata.)

Samadel põhjustel versioneerime ka tüüpe. Omandasime meie tüübist süsteemi detailse ülevaate. eelmises postituses.

Funktsioonide ja tüüpide versioonimise abil saate oma rakendusse muudatusi järk-järgult sisse viia. Iga eraldi töötleva funktsiooni toimivust saab kontrollida uue versiooniga, ilma et peaksite kõik muudatused rakendusse samaaegselt tooma (kuid meil on tööriistad, et seda kiiresti teha, kui soovite).

See on palju turvalisem kui kogu korraga täielik juurutamine, nagu see praegu on.

Uued pakettide versioonid ja standardne teek

Kui värskendate paketti Darkis, ei asenda me kohe iga funktsiooni või tüübi kasutamist kogu koodibaasis. See ei ole ohutu. Kood kasutab endiselt sama versiooni, mida ta kasutas, samas kui te värskendate funktsioonide ja tüüpide kasutamist uue versiooniga iga eraldi juhtumi jaoks lülitite abil.

Kuidas Dark käivitab koodi 50 ms jooksul
Kuvatõmmis Darki automaatprotsessist, mis näitab kahte versiooni funktsioonist Dict::get. Dict::get_v0 tagastas tüübi Any (millest me loobume), samas kui Dict::get_v1 tagastab tüübi Option.

Meie teenus pakub sageli uusi funktsioone, samas kõrvaldades vanad versioonid. Kasutajad, kellel on vanad versioonid, saavad neid oma koodis jätkuvalt kasutada, kuid uued kasutajad ei pääse neile ligi. Kavatseme pakkuda tööriistu, et viia kasutajad vanadelt versioonidelt uutele ühe sammuga, samuti funktsiooni lülitite abil.

Dark pakub ka ainulaadset võimalust: kuna me jooksutame teie töökoodi, saame ise uusi versioone testida, võrreldes uusite ja vanade päringute väljundeid, et teavitada teid muudatustest. Seetõttu on pakettide uuendamine, mis sageli toimub pimesi (või nõuab põhjalikku testimist turvalisuse huvides), palju vähem riskantne ning võib toimuda automaatselt.

Uued versioonid Dark

Üleminek Python 2-lt Python 3-le venis kümnendiks ja on endiselt probleem. Kuna arendame Dark'i pideva tarnimise jaoks, peame arvesse võtma neid keele muutusi.

Kui teeme keeles väikseid muudatusi, loome uue versiooni Dark. Vana kood jääb vana versiooni Darki alla ja uus kood kasutatakse uues versioonis. Uue versiooni Darki kasutamiseks saab kasutada lülitusi või funktsiooniversioone.

See on eriti kasulik, arvestades, et Dark on hiljuti ilmunud. Paljud keele või teegi muudatused võivad olla ebaõnnestunud. Keeles järkjärguline versioonimine võimaldab meil teha väikeseid uuendusi, st saame mitte kiirustada ja edasi lükata paljusid keelealaseid otsuseid, kuni meil on rohkem kasutajaid ja seega rohkem teavet.

Andmebaasi migratsioonid

Ohutuks andmebaasi migratsiooniks on olemas standaardne valem:

  • Koodi ümber kirjutamine uute ja vanade formaatide toetamiseks
  • Kõik andmed uude formaati ümber muuta
  • Eemaldada vana andmete ligipääs

Tulemuseks on andmebaasi migratsioon, mis venib ja nõuab palju ressursse. Meil tekivad vananenud skeemid, sest isegi lihtsad ülesanded, nagu tabeli või veeru nime parandamine, ei õigusta kulutatud pingutusi.

Darkis on tõhus andmebaaside migratsiooniplatvorm, mis (me loodame) muudab protsessi nii lihtsaks, et te ei karda seda enam. Kõik Darki andmehoidlad („võti-väärtus” hoidlatega või püsihash-tabelid) on tüübi all. Andmehoidla migreerimiseks lihtsalt määrate sellele uue tüübi ja taastamis- ja taaskäivitamisfunktsiooni, et muuta väärtusi kahe tüübi vahel.

Darkis pääseb andmehoidlatesse versioonitud muutujanimede kaudu. Näiteks nimetatakse Users andmehoidlat algselt Users-v0. Kui luuakse uus versioon teistsuguse tüübiga, muutub nimi Users-v1. Kui andmed on salvestatud Users-v0 kaudu ja pääsete neile ligi Users-v1 kaudu, rakendatakse taaskäivitamisfunktsiooni. Kui andmed on salvestatud Users-v1 kaudu ja pääsete neile ligi Users-v0 kaudu, rakendatakse taastamisfunktsiooni.

Kuidas Dark käivitab koodi 50 ms jooksul
Andmebaasi migratsiooni ekraan koos vana andmebaasi väljanimedega, taaskäivitamis- ja taastamisavaldistega ning juhistega migratsiooni võimaldamiseks.

Kasutage funktsioonide lüliteid, et suunata kutseid Users-v0 versioonile Users-v1. Seda saab teha ühe HTTP-osta käsitleja kaupa, et vähendada riske, ja lülitid töötavad individuaalsetele kasutajatele, et saaksite kontrollida, kas kõik töötab nagu oodatud. Kui Users-v0 kasutajad on kadunud, teisendab Dark kõik ülejäänud andmed taustal vanast formaadist uude. Te ei pruugi seda isegi märgata.

Testimine

Dark on funktsionaalne programmeerimiskeel staatilise tüpiseerimisega ja muutumatute väärtustega, seetõttu on selle testimise pind vähenenud võrreldes objektorienteeritud keeltesse dünaamilise tüpiseerimisega. Kuid testimine on ikkagi vajalik.
Darkis käivitab redaktor automaatselt moodultestid taustal redigeeritava koodi jaoks ja koos standardse testimise kõigi funktsioonide lülitite jaoks. Tulevikus tahame staatiliste tüüpide abil automaatselt teostada koodi fuzzingut, et avastada vigu.

Lisaks sellele haldab Dark teie infrastruktuuri tootmises, avades uusi võimalusi. Me salvestame automaatselt HTTP-päringud Dark infrastruktuuris (hetkel salvestame kõik päringud, kuid plaanime hiljem minna valikule). Testime nende põhjal uut koodi ja teeme moodulitestid, ning soovi korral saate hõlpsasti huvitavad päringud mootuli testideks muuta.

Mille me oleme lõpetanud

Kuna meil ei ole juurutamist, kuid on funktsioonide lülitid, jääb umbes 60% juurutustsüklist kõrvale. Me ei vaja git harusid või pull-requeste, backend-ressursside ja konteinerite koostamist, ressursside ja konteinerite saatmist registritesse ega juurutamise samme Kuberneteses.

Kuidas Dark käivitab koodi 50 ms jooksul
Tavapärase jätkuva tarnetoru (vasakul) ja Darki pideva tarnimise (paremal) võrdlus. Darkis koosneb tarnimine 6 sammust ja ühest tsüklist, samas kui traditsiooniline versioon sisaldab 35 sammu ja 3 tsüklit.

Darkis on juurutamiseks vaid 6 sammu ja 1 tsükkel (sammud, mis korduvad mitu korda), samas kui kaasaegne pideva tarnimise torujuhe koosneb 35 sammust ja 3 tsüklist. Darkis käivitatakse testid automaatselt, ja te isegi ei märka seda; sõltuvused installitakse automaatselt; kõik, mis on seotud gitiga või Githubiga, pole enam vajalik; Docker konteinerite kogumine, testimine ja saatmine pole vajalik; juurutamine Kuberneteses pole enam vajalik.

I isegi jäänud sammud Darkis on muutunud lihtsamaks. Kuna funktsioonide lülititega saab hallata ühe tegevusega, ei ole enam vajalik terve juurutamistorujuhe läbi käia, et vana kood eemaldada.

Oleme kodeerimise tarnimise lihtsustamiseks kasutusele võtnud meetodeid, mis vähendavad pideva tarnimise aega ja riske. Samuti oleme oluliselt lihtsustanud pakettide uuendamist, andmebaasi migreerimist, testimist, versioonihaldust, sõltuvuste installimist, arendus- ja tootmis keskkonna võrdsustamist ning kiireid ja turvalisi keele versiooniuuendusi.

Vastan neile küsimustele HackerNewsis.

Kuna soovite rohkem teada Darki seadistuse kohta, lugege artiklit Darkist, ja jälgige meid Twitteris (või mind) või registreeru beetaversioon ja saa teateid järgmistest postitustest. Kui suundud Septembris StrangeLoop'i, tule meie avamisele.

Allikas: habr.com

Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid 🔥 Osta usaldusväärne veebihosting DDoS kaitsega, VPS VDS serverid | ProHoster