Kako Dark izvaja kodo v 50 ms

Kako Dark izvaja kodo v 50 ms

Čím rychlejší je vývojový proces, tím rychleji se rozvíjí technologická společnost.

Bohužel moderní aplikace pracují proti nám — naše systémy musí být aktualizovány v reálném čase a zároveň nikomu nepřekážet a nevedou k výpadkům. Nasazení v takových systémech se stává složitým úkolem a vyžaduje složité kanály kontinuální dodávky i v malých týmech.

Tyto kanály obvykle mají úzké využití, pracují pomalu a nejsou spolehlivé. Vývojáři je musí nejdříve vytvořit ručně a poté je spravovat, a společnosti často najímají celé týmy DevOps, aby se o to postaraly.

Rychlost těchto kanálů ovlivňuje rychlost vývoje. U nejlepších týmů nasazení zabere 5–10 minut, ale obvykle trvá mnohem déle a jedno nasazení může trvat několik hodin.

Ve společnosti Dark to zabere 50 ms. Padesát. Milisekund.. Dark — je komplexní řešení s programovacím jazykem, editorem a infrastrukturou, vytvořené speciálně pro kontinuální dodávku, a všechny aspekty Dark, včetně samotného jazyka, jsou navrženy s ohledem na bezpečné okamžité nasazení.

Proč jsou kanály kontinuální dodávky tak pomalé?

Představme si, že máme webovou aplikaci Python a již jsme vytvořili skvělý a moderní kanál kontinuální dodávky. Pro vývojáře, který se touto činností zabývá každý den, bude nasazení jediné drobné změny vypadat přibližně takto:

Provádění změn

  • Vytvoření nového větvení v gitu
  • Provádění změn za přepínačem funkcí
  • Modulové testování k ověření změn s přepínačem funkcí i bez něj

Pull request

  • Záznam změn
  • Odeslání změn do vzdáleného repozitáře na githubu
  • Pull request
  • Sestavení CI se provádí automaticky na pozadí
  • Kontrola kódu
  • Další kontroly kódu, pokud jsou potřeba
  • Sloučení změn s větví git master.

CI se provádí na větvi master

  • Instalace frontendových závislostí přes npm
  • Sestavení a optimalizace zdrojů HTML+CSS+JS
  • Provedení modulových a funkčních testů na frontendu
  • Instalace závislostí Pythonu z PyPI
  • Provedení modulových a funkčních testů na backendu
  • Testování integrace na obou koncích
  • Odeslání zdrojů frontendu do CDN
  • Sestavení kontejneru pro program Python
  • Pošiljanje kontejnerja v register
  • Posodobitev manifestov Kubernetes

Zamenjava stare kode z novo

  • Kubernetes zažene več primerkov novega kontejnerja
  • Kubernetes čaka, da postanejo primerki operativni
  • Kubernetes dodaja primerke v HTTP uravnoteževalnik obremenitve
  • Kubernetes čaka, da se starejši primerki prenehajo uporabljati
  • Kubernetes ustavi starejše primerke
  • Kubernetes ponavlja te operacije, dokler novi primerki ne zamenjajo vseh starih

Vključitev novega stikala funkcij

  • Nova koda se vklopi le za sebe, da se prepriča, da je vse v redu
  • Nova koda se vklopi za 10 % uporabnikov, spremljajo se operativne in poslovne metrike
  • Nova koda se vklopi za 50 % uporabnikov, spremljajo se operativne in poslovne metrike
  • Nova koda se vklopi za 100 % uporabnikov, spremljajo se operativne in poslovne metrike
  • Nazadnje ponovite celoten postopek, da odstranite staro kodo in stikalo

Postopek je odvisen od orodij, jezika in uporabe arhitektur, usmerjenih na storitve, vendar v splošnem izgleda tako. Nisem omenil uvajanja z migracijo baz podatkov, ker to zahteva skrbno načrtovanje, toda spodaj bom razložil, kako s tem ravna Dark.

Tukaj je veliko komponent in mnoge od njih lahko zlahka ustavijo sistem, povzročijo težave, sprožijo začasno konkurenco ali zrušijo delovni sistem.

Ker so ti cevovodi skoraj vedno ustvarjeni za posebne primere, nanje težko računamo. Veliko ljudi ima dni, ko kode ni mogoče uvesti, ker je v Dockerfile težava, eden od desetih storitev je odpovedal ali pa je potreben strokovnjak na dopustu.

Še huje, mnogi od teh korakov sploh ne prinašajo koristnega. Bili so potrebni prej, ko smo uvajali kodo neposredno za uporabnike, zdaj pa imamo stikalnike za novo kodo in so ti procesi ločeni. Na koncu je korak, kjer se koda uvaja (stara se nadomesti z novo), zdaj preprosto odvečna tveganja.

Seveda, to je zelo premišljen cevovod. Ekipa, ki ga je ustvarila, ni skoparila s časom in denarjem za hitro uvajanje. Običajno so cevovodi za uvajanje veliko počasnejši in manj zanesljivi.

Izvedba neprekinjene oskrbe v Dark

Neprekinjena dostava je za Dark toliko važna da smo od samog početka ciljali na vreme ispod jedne sekunde. Prošli smo kroz sve korake u lancu opskrbe kako bismo uklonili sve suvišne, a ostalo doveli do savršenstva. Evo kako smo uklonili korake.

Džesi Frazel (Jessie Frazelle) je smislila novu reč deployless (ne zahteva implementaciju) na konferenciji Future of Software Development u Rejkjaviku.

Odmah smo odlučili da će Dark biti zasnovan na konceptu „deployless“ (hvala Džesi Frazel na neologizmu). Deployless znači da se svaki kod momentalno implementira i spreman je za proizvodnju. Naravno, nećemo propustiti neispravan ili nepotpun kod (principi bezbednosti biće objašnjeni u nastavku).

Na demonstraciji Dark često su nas pitali kako smo uspeli tako da ubrzamo implementaciju. Čudan pitanje. Ljudi verovatno misle da smo smislili neku super tehnologiju koja poredi kod, kompajlira ga, upakuje u kontejner, pokreće virtuelnu mašinu, pokreće kontejner hladno i sve to za 50 ms. To je malo verovatno. Ali smo stvorili poseban motor za implementaciju kome to nije ni potrebno.

Dark pokreće interpretere u oblaku. Recimo, pišete kod u funkciji ili HTTP ili događajnom handleru. Šaljemo diff u apstraktno sintaktičko stablo (implementaciju koda koju interno koristi naš uređivač i serveri) na naše servere, a zatim pokrećemo taj kod kada dobijemo zahteve. Tako da implementacija izgleda kao skromni unos u bazu podataka — momentalna i jednostavna. Implementacija se odvija tako brzo jer uključuje minimum.

U budućnosti planiramo da od Dark napravimo kompajler infrastrukture koji će kreirati i pokretati savršenu infrastrukturu za visoke performanse i pouzdanost aplikacija. Momentna implementacija, naravno, neće nestati.

Sigurna implementacija

Strukturirani uređivač

Kod u Dark piše se u uređivaču Dark. Strukturirani uređivač ne dozvoljava sintaktičke greške. U suštini, u Dark čak i nema analizirača. Dok kucate tekst, direktno radimo sa apstraktnim sintaktičkim stablom (AST), kao Paredit, Sketch-n-Sketch, Tofu, Prune in MPS.

Svi nedovršeni kodovi u Dark imaju dozvoljenu semantiku izvršavanja, otprilike kao tipizovane rupe u Hazelu. Na primjer, ako promijenite poziv funkcije, čuvamo staru funkciju dok nova ne postane spremna.

Svaki program u Darku ima svoju svrhu, stoga nedovršeni kod ne ometa rad završenog.

Načini uređivanja

Kod u Darku pišete u dva slučaja. Prvi: pišete novi kod i jedini ste korisnik. Na primjer, to je u REPL-u, a drugi korisnici nikada neće imati pristup njemu, ili je to nova HTTP staza na koju se nigdje ne pozivate. Ovde možete raditi bez ikakvih mjera opreza, a sada upravo tako radite u razvojnom okruženju.

Druga situacija: kod se već koristi. Ako kroz kod prolazi promet (funkcije, obrada događaja, baze podataka itd.), trebate biti oprezni. Zbog toga blokiramo sav korišteni kod i zahtijevamo korištenje strukturiranijih alata za njegovo uređivanje. O strukturiranim alatima ću govoriti u nastavku: prekidači funkcija za HTTP i događaje, moćna platforma za migraciju baza podataka i nova metoda upravljanja verzijama za funkcije i tipove.

Prekidači funkcija

Jedan od načina uklanjanja suvišne složenosti u Darku je riješiti nekoliko problema jednim rješenjem. Prekidači funkcija obavljaju mnoge različite zadatke: zamjena lokalnog razvojnog okruženja, git grane, implementacija koda i naravno, tradicionalno sporo i kontrolisano puštanje novog koda.

Kreiranje i implementacija prekidača funkcija vrši se u našem uređivaču u jednoj operaciji. On stvara prazno mjesto za novi kod i pruža kontrole pristupa starom i novom kodu, kao i dugmad i komande za postepeno prebacivanje na novi kod ili njegovu isključenje.

Prekidači funkcija ugrađeni su u jezik Dark, i čak i nedovršeni prekidači obavljaju svoju funkciju – ako uslov u prekidaču nije ispunjen, izvršiće se stari blokirani kod.

Razvojno okolje

Preklopniki funkcij nadomeščajo lokalno razvojno okolje. Danes je ekipam težko poskrbeti, da vsi uporabljajo enake različice orodij in knjižnic (orodja za oblikovanje kode, linters, upravljalniki paketov, prevajalniki, predprocesorji, orodja za testiranje itd.). S Dark ni treba lokalno namestiti odvisnosti, upravljati z lokalno namestitvijo Dockerja ali sprejeti drugih ukrepov, da bi zagotovili vsaj nekakšno enakost med razvojnim okoljem in produkcijo. Glede na to, da taka enakost kljub vsemu ni mogoča,, se niti pretvarjati ne bomo, da si prizadevamo zanjo.

Namesto da bi ustvarili klonirano lokalno okolje, preklopniki v Dark ustvarjajo novo peskovnik v produkciji, ki zamenja razvojno okolje. V prihodnosti načrtujemo tudi ustvarjanje peskovnika za druge dele aplikacije (na primer trenutne klone baz podatkov), čeprav se to trenutno ne zdi tako pomembno.

Veje in razmestitev

Trenutno obstaja več načinov za vnos nove kode v sisteme: git veje, faza razmestitve in preklopniki funkcij. Rešujejo enak problem na različnih delih delovnega toka: git – na fazah pred razmestitvijo, razmestitev – ob prehodu s stare kode na novo, preklopniki funkcij – za nadzorovano izdajo nove kode.

Najbolj učinkovit način so preklopniki funkcij (hkrati tudi najlažje razumeti in uporabljati). Z njimi se lahko popolnoma odrečemo ostalim dvema metodama. Še posebej koristno je odstraniti razmestitev – če že uporabljamo preklopnike funkcij, da vključimo kodo, potem korak prenosa strežnikov na novo kodo povzroča le dodatna tveganja.

Git je težko uporabljati, še posebej novakom, kar ga zelo omejuje, a ima priročne veje. Odpravili smo mnoge pomanjkljivosti gita. Dark se ureja v realnem času in omogoča sodelovanje v slogu Google Dokumentov, da ni treba pošiljati kode in da je manj pogosto potrebno izvajati rebase in merge.

Funkcijski prekidači su temelj sigurnog implementiranja. Zajedno s trenutnim implementacijama, omogućuju brzo testiranje koncepata u malim fragmentima s niskim rizikom umjesto primjene jedne velike promjene koja bi mogla srušiti sustav.

Верзионисање

Za promjenu funkcija i tipova koristimo verzioniranje. Ako želite promijeniti funkciju, Dark stvara novu verziju te funkcije. Nakon toga, tu verziju možete pozvati putem prekidača u HTTP handleru ili događaju. (Ako je ta funkcija duboko u grafu poziva, usput se stvara nova verzija svake funkcije. Može se činiti da je to prekomjerno, ali funkcije se ne sudaraju kad ih ne koristite, tako da to niti ne primijetite.)

Iz istih razloga verzioniramo i tipove. O našem sustavu tipova detaljno smo govorili u prethodnom postu..

Zahvaljujući verzioniranju funkcija i tipova, možete postupno uvoditi promjene u aplikaciju. Možete provjeriti da svaki pojedinačni handler radi s novom verzijom, a nije potrebno odmah provesti sve promjene u aplikaciji (ali imamo alate koji omogućuju brzo to ako želite).

To je mnogo sigurnije od potpunog implementiranja svega odjednom, kao što se to događa sada.

Nove verzije paketa i standardna biblioteka

Kada ažurirate paket u Darku, ne zamjenjujemo odmah korištenje svake funkcije ili tipa u cijeloj bazi koda. To nije sigurno. Kod nastavlja koristiti istu verziju koju je koristio, a vi ažurirate korištenje funkcija i tipova na novu verziju za svaki pojedinačni slučaj putem prekidača.

Kako Dark izvaja kodo v 50 ms
Snimak dijela automatskog procesa u Darku, koji pokazuje dvije verzije funkcije Dict::get. Dict::get_v0 je vraćao tip Any (od kojeg odustajemo), dok Dict::get_v1 vraća tip Option.

Često pružamo novu funkciju u standardnoj biblioteci i isključujemo stare verzije. Korisnici sa starim verzijama koda zadržat će pristup njima, ali novi korisnici ih neće moći dobiti. Planiramo pružiti alate koji će omogućiti prijelaz korisnika sa starih verzija na nove u 1 koraku, opet putem prekidača funkcija.

Dark prav tako ponuja edinstveno priložnost: ker izvajamo vašo delovno kodo, lahko sami testiramo nove različice in primerjamo izhodne podatke za nove in stare poizvedbe, da vas obvestimo o spremembah. Posledično posodobitev paketov, ki se pogosto izvaja na slepo (ali zahteva natančno testiranje iz varnostnih razlogov), predstavlja veliko manj tveganj in se lahko izvaja samodejno.

Nove različice Dark

Prehod s Pythona 2 na Python 3 se je raztezal čez desetletje in še vedno predstavlja težavo. Ker ustvarjamo Dark za neprekinjeno dostavo, je treba upoštevati te spremembe jezika.

Ko vnašamo majhne spremembe v jezik, ustvarjamo novo različico Dark. Stara koda ostane v stari različici Dark, nova koda pa se uporablja v novi različici. Za prehod na novo različico Dark lahko uporabite preklopnike ali različice funkcij.

To je še posebej koristno, ker je Dark nastal šele nedavno. Mnoge spremembe v jeziku ali knjižnici se lahko izkažejo za neuspešne. Postopno verzioniranje jezika nam omogoča, da delamo majhne posodobitve, kar pomeni, da se lahko ne mudi in odložimo številne odločitve o jeziku, dokler ne bomo imeli več uporabnikov in torej več informacij.

Migracije baz podatkov

Za varno migracijo baze podatkov obstaja standardna formula:

  • Prepisati kodo za podporo novim in starim formatom
  • Pretvoriti vse podatke v nov format
  • Odstraniti star dostop do podatkov

Zaradi tega se migracija baze podatkov zamakne in zahteva veliko virov. In nagomilamo zastarele sheme, saj tudi preproste naloge, kot je popravilo imena tabele ali stolpca, ne upravičujejo stroškov.

Dark ima učinkovito platformo za migracijo baz podatkov, ki (upamo) tako poenostavi postopek, da se ga ne boste več bali. Vse shrambe podatkov v Dark (hranilniki parov „ključ-vrednost“ ali trajne hasho-tabele) imajo tip. Da bi prenesli shrambo podatkov, ji preprosto dodelite nov tip in funkcijo za povratno in napredno operacijo za pretvorbo vrednosti med obema tipoma.

Dostop do podatkovnih skladišč v Darku se izvaja prek verzioniranih imen spremenljivk. Na primer, podatkovno skladišče Users se sprva imenuje Users-v0. Ko je ustvarjena nova različica z drugačnim tipom, se ime spremeni v Users-v1. Če so podatki shranjeni prek Users-v0, ko pa dostopate do njih prek Users-v1, se uporabi funkcija vračanja. Če so podatki shranjeni prek Users-v1, ko dostopate do njih prek Users-v0, se uporabi funkcija povratka.

Kako Dark izvaja kodo v 50 ms
Zaslon za migracijo baze podatkov s trenutnimi imeni polj stare baze podatkov, izrazi vračanja in povratka ter navodili za vključitev migracije.

Uporabite stikala za funkcije, da usmerite klice z Users-v0 na različico Users-v1. To lahko storite enega HTTP obdelovalnika naenkrat, kar zmanjša tveganja, poleg tega stikala delujejo za posamezne uporabnike, s čimer lahko preverite, da vse deluje, kot je bilo pričakovano. Ko uporabnikov Users-v0 ne bo več, Dark vse preostale podatke v ozadju pretvori iz starega formata v novega. Tega sploh ne boste opazili.

Testiranje

Dark je funkcionalni programski jezik s statično tipizacijo in nespremenljivimi vrednostmi, zato je površina testiranja precej manjša v primerjavi z objektno usmerjenimi jeziki z dinamično tipizacijo. Vendar testiranje ostaja nujno.
V Darku samodejno zažene modulne teste v ozadju za urejen kodo in privzeto izvaja te teste za vsa stikala funkcij. V prihodnosti želimo z uporabo statičnih tipov samodejno izvajati fuzzing kode za iskanje napak.

Poleg tega Dark obsega vašo infrastrukturo v produkciji, kar odpira nove možnosti. Samodejno shranjujemo HTTP zahteve v infrastrukturi Dark (zaenkrat shranjujemo vse zahteve, pozneje pa želimo preiti na vzorčenje). Testiramo nov kod glede na te zahteve in izvajamo modulne teste, ter po želji lahko enostavno pretvorite zanimive zahteve v modulne teste.

Od česar smo se odpovedali

Ker nimamo nalaganja, imamo pa stikala funkcij, približno 60% procesa nalaganja ostane neizkoriščenih. Ne potrebujemo git vejah ali pull zahtevkov, gradnje backend virov in kontejnerjev, pošiljanja virov in kontejnerjev v registre ali korakov nalaganja v Kubernetes.

Kako Dark izvaja kodo v 50 ms
Primerjava standardnega pipelinea neprekinjenega oskrbovanja (levo) in neprekinjeno oskrbovanje Dark (desno). V Dark oskrba obsega 6 korakov in en cikel, medtem ko tradicionalna različica vključuje 35 korakov in 3 cikle.

V Dark je razporeditev sestavljena le iz 6 korakov in 1 cikla (koraki, ki se ponavljajo večkrat), medtem ko sodoben pipeline neprekinjenega oskrbovanja obsega 35 korakov in 3 cikle. V Dark se testi izvajajo samodejno, kar vam ne pride niti na misel; odvisnosti se nameščajo samodejno; vse, kar je povezano z git ali Github, več ni potrebno; zbiranje, testiranje in pošiljanje Docker kontejnerjev ni potrebno; razporejanje v Kubernetes ni več potrebno.

Tudi preostali koraki v Dark so postali enostavnejši. Ker je mogoče upravljati s preklopniki funkcij z eno akcijo, ni treba znova prehajati skozi celoten razporedilni pipeline, da bi odstranili stari kodo.

Po najboljših močeh smo poenostavili dostavo kode, skrajšali čas in tveganja neprekinjenega oskrbovanja. Poleg tega smo močno poenostavili posodobitve paketov, migracije baz podatkov, testiranje, obvladovanje različic, namestitev odvisnosti, usklajenost med razvojnim in produkcijskim okoljem ter hitre in varne nadgradnje jezikovnih različic.

O tem odgovarjam na HackerNews.

Da bi izvedeli več o napravi Dark, preberite članek o Dark, sledite nam na Twitterju (ali na meni) nebo prijavite se na beta različico in prejemajte obvestila o prihodnjih objavah. Če se v septembru odpravite na StrangeLoop, pridite na naš zagon.

Izvor: habr.com

Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki 🔥 Kupite zanesljivo gostovanje za spletne strani z zaščito pred DDoS, VPS VDS strežniki | ProHoster