
Što je brži razvojni proces, to se brže razvija tehnološka tvrtka.
Nažalost, moderna aplikacija radi protiv nas — naši sustavi moraju se ažurirati u stvarnom vremenu i pritom nikome ne smetati i ne uzrokovati prekide i zastoje. Implementacija u takvim sustavima postaje težak zadatak i zahtijeva složene cjevovode kontinuirane isporuke čak i u malim timovima.
Ovi cjevovodi obično imaju usku primjenu, sporo rade i nisu pouzdani. Programeri ih prvo moraju stvoriti ručno, a zatim njima upravljati, zbog čega tvrtke često zapošljavaju cijele DevOps timove.
Brzina ovih cjevovoda određuje brzinu razvoja. U najboljim timovima implementacija traje 5–10 minuta, ali obično se sve odvija mnogo sporije, a za jednu implementaciju potrebno je nekoliko sati.
U Darku to traje 50 ms. Pedeset. Milisekundi. Dark — , stvoreno posebno za kontinuiranu isporuku, a svi aspekti Darka, uključujući sam jezik, izgrađeni su s ciljem sigurnog trenutnog implementiranja.
Zašto su cjevovodi kontinuirane isporuke tako spori?
Pretpostavimo da imamo web-aplikaciju u Pythonu i već smo stvorili fantastičan i suvremen cjevovod kontinuirane isporuke. Za programera koji se svakodnevno bavi ovim projektom, implementacija jedne male promjene izgledat će otprilike ovako:
Unos promjena
- Stvaranje nove grane u gitu
- Unos promjena preko preklopnog prekidača
- Modularno testiranje za provjeru promjena s i bez preklopnog prekidača
Pull zahtjev
- Commit promjena
- Slanje promjena u udaljeni repozitorij na githubu
- Pull zahtjev
- CI se automatski izvodi u pozadini
- Recenzija koda
- Još nekoliko recenzija, ako je potrebno
- Spajanje promjena s master gitom.
CI se izvodi na masteru
- Instalacija frontend ovisnosti preko npm-a
- Gradnja i optimizacija HTML+CSS+JS resursa
- Pokretanje modularnih i funkcionalnih testova na frontendu
- Instalacija ovisnosti Pythona iz PyPI
- Pokretanje modularnih i funkcionalnih testova na backendu
- Testiranje integracije na oba kraja
- Slanje frontend resursa u CDN
- Gradnja kontejnera za program Python
- Slanje kontejnera u registar
- Ažuriranje Kubernetes manifesta
Zamjena starog koda novim
- Kubernetes pokreće više instanci novog kontejnera
- Kubernetes čeka da instance postanu operativne
- Kubernetes dodaje instance u HTTP ravnotežnik opterećenja
- Kubernetes čeka da se stare instance prestanu koristiti
- Kubernetes zaustavlja stare instance
- Kubernetes ponavlja ove operacije sve dok nove instance ne zamijene sve stare
Aktivacija novog prekidača funkcionalnosti
- Novi kod se aktivira samo za sebe kako bi se osiguralo da sve funkcioniše ispravno
- Novi kod se aktivira za 10% korisnika, prate se operativne i poslovne metrike
- Novi kod se aktivira za 50% korisnika, prate se operativne i poslovne metrike
- Novi kod se aktivira za 100% korisnika, prate se operativne i poslovne metrike
- Na kraju, ponavljate cijeli postupak kako biste uklonili stari kod i prekidač
Proces ovisi o alatima, jeziku i korištenju arhitektura usmjerenih na usluge, ali u načelu izgleda ovako. Nije spomenuto implementiranje s migracijom baza podataka, jer to zahtijeva detaljno planiranje, ali dalje ću objasniti kako se time bavi Dark.
Ovdje ima mnogo komponenti, a mnoge od njih lako mogu usporiti, srušiti se, izazvati privremenu konkurenciju ili oboriti radni sustav.
A pošto su ovi ciklusi gotovo uvijek kreirani za posebne slučajeve, na njih je teško osloniti se. Mnogi imaju dane kada kod nije moguće implementirati jer postoje problemi u Dockerfileu, neki od desetaka servisa se sruše ili je potreban stručnjak na odmoru.
Štaviše, mnogi od ovih koraka zapravo ne čine ništa korisno. Bili su potrebni ranije, kada smo implementirali kod odmah za korisnike, ali sada imamo prekidače za novi kod, a ovi procesi su se razdvojili. Kao rezultat toga, korak koji implementira kod (stari se zamjenjuje novim) sada je postao samo nepotreban rizik.
Naravno, ovo je vrlo promišljen pipeline. Tim koji ga je stvorio nije štedio vrijeme i novac za brzo implementiranje. Obično su pipeline-ovi implementacije mnogo sporiji i nepouzdaniji.
Implementacija kontinuirane isporuke u Dark
Kontinuirana isporuka je toliko važna za Dark da smo od samog početka ciljali na vrijeme kraće od jedne sekunde. Pregledali smo sve korake u procesu kako bismo uklonili sve suvišne, a ostalo dovedeno do savršenstva. Evo kako smo uklonili korake.
Jessie Frazelle () je smislila novu riječ deployless (bez potrebe za implementacijom) na konferenciji Future of Software Development u Rejkjaviku.
Odmah smo odlučili da će Dark biti zasnovan na konceptu 'deployless' (hvala za neologizam). Deployless označava da se svaki kod trenutačno implementira i spreman je za korištenje u produkciji. Naravno, nećemo propustiti neispravan ili nepotpun kod (principi sigurnosti ću opisati u nastavku).
Na demonstraciji Dark često su nas pitali kako smo uspjeli ubrzati implementaciju. Čudan вопрос. Ljudi vjerojatno misle da smo smislili neku super tehnologiju koja uspoređuje kod, kompajlira ga, pakira u kontejner, pokreće virtualnu mašinu, pokreće kontejner hladno i sve to za 50 ms. Mogućnost tog tipa je malo vjerojatna. Ali smo razvili poseban motor implementacije kojemu to sve i nije potrebno.
Dark pokreće interpretere u oblaku. Recimo, pišete kod u funkciji ili HTTP-handleru ili događaju. Š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 kad dobijemo zahtjeve. Tako da implementacija izgleda kao skromni unos u bazu podataka — trenutna i jednostavna. Implementacija se odvija tako brzo jer uključuje minimum.
U budućnosti planiramo učiniti od Darka kompajler infrastrukture koji će stvarati i pokretati idealnu infrastrukturu za visoke performanse i pouzdanost aplikacija. Trenutna implementacija, naravno, neće nestati.
Sigurna implementacija
Strukturirani uređivač
Kod u Darku piše se u uređivaču Dark. Strukturirani uređivač ne dopušta sintaktičke greške. U suštini, u Darku nema ni analizatora. Dok unosite tekst, direktno radimo s apstraktnim sintaktičkim stablom (AST), kao , , , i .
Svaki nedovršeni kod u Darku ima valjanu semantiku izvršavanja, otprilike kao . Na primjer, ako promijenite poziv funkcije, čuvamo staru funkciju dok nova ne postane spremna.
Svaki program u Dark ima svoj smisao, tako da nekompletan kod ne ometa rad završenog.
Načini uređivanja
Kôd u Darku pišete u dva slučaja. Prvi: pišete novi kôd i jedini ste korisnik. Na primjer, radi se u REPL-u, a ostali korisnici nikada neće imati pristup tome, ili je to nova HTTP ruta kojoj se nigde ne referencirate. U tom slučaju možete raditi bez ikakvih mjera opreza i sada upravo tako radite u razvojnim okruženju.
Druga situacija: kod se već koristi. Ako kroz kod prolazi promet (funkcije, obrada događaja, baze podataka, tipa), treba biti oprezan. U tu svrhu blokiramo sav korišteni kod i zahtijevamo korištenje strukturiranijih alata za njegovo uređivanje. O strukturiranim alatima ću govoriti u nastavku: preklopnici funkcija za HTTP obradu i događaje, moćna platforma za migraciju za baze podataka i nova metoda upravljanja verzijama za funkcije i tipove.
Preklopnici funkcija
Jedan od načina u Darku je riješiti nekoliko problema jednim rješenjem. Preklopnici funkcija izvršavaju mnogo različitih zadataka: zamjena lokalnog razvojnog okruženja, git grane, implementacija koda i, naravno, tradicionalno sporo i kontrolirano objavljivanje novog koda.
Kreiranje i implementacija preklopnika funkcija obavlja se u našem uređivaču u jednom koraku. Stvara prazno polje za novi kôd i pruža kontrole pristupa starom i novom kodu, kao i gumbe i naredbe za postepeno prelazak na novi kod ili njegovo isključivanje.
Preklopnici funkcija ugrađeni su u jezik Dark, a čak i nekompletni preklopnici obavljaju svoju funkciju — ako uvjet u preklopniku nije ispunjen, izvršit će se stari blokirani kod.
Razvojno okruženje
Preklopnici funkcija zamjenjuju lokalno razvojno okruženje. Danas je timovima teško pratiti da svi koriste iste verzije alata i knjižnica (alati za formatiranje koda, linters, upravitelji paketa, kompajleri, preprocesori, alati za testiranje itd.). S Darkom nije potrebno instalirati ovisnosti lokalno, upravljati lokalnom instalacijom Dockera ili poduzimati druge mjere kako bi se osiguralo barem neko podudaranje između razvojnog i produkcijskog okruženja. , čak se ni ne pretvaramo da težimo tome.
Umjesto da stvorimo klonirano lokalno okruženje, preklopnici u Darku stvaraju novu pješčanik u produkciji koja zamjenjuje razvojno okruženje. U budućnosti također planiramo stvoriti pješčanik za druge dijelove aplikacije (na primjer, trenutne klonove baza podataka), iako to trenutno ne izgleda toliko važno.
Grane i implementacije
Trenutno postoji nekoliko načina unosa novog koda u sustave: git grane, faza implementacije i preklopnici funkcija. Oni rješavaju jedan problem u različitim dijelovima radnog procesa: git — u fazama prije implementacije, implementacija — u trenutku prelaska s starog na novi kod, a preklopnici funkcija — za kontrolirano puštanje novog koda.
Najefikasniji način su preklopnici funkcija (uz to, najjednostavniji za razumjeti i koristiti). S njima se može potpuno odustati od preostalih dvaju metoda. Osobito je korisno ukloniti implementaciju — ako ionako koristimo preklopnike funkcija za aktivaciju koda, tada korak prebacivanja servera na novi kod samo stvara dodatne rizike.
Git je teško koristiti, posebno početnicima, i to ozbiljno ograničava, ali zato ima zgodne grane. Ispravili smo mnoge nedostatke git-a. Dark se može uređivati u stvarnom vremenu i omogućuje suradnju u stilu Google Dokumenata, tako da nije potrebno slati kod i rjeđe se može izvoditi rebaziranje i spajanje.
Prekidači funkcija predstavljaju osnovu sigurnog implementiranja. Zajedno s trenutačnim implementacijama omogućuju brzo testiranje koncepata u malim dijelovima s niskim rizikom umjesto primjene jedne velike promjene koja može srušiti sustav.
Verzionarstvo
Za promjenu funkcija i tipova koristimo verzioniranje. Ako želite promijeniti funkciju, Dark stvara novu verziju te funkcije. Zatim možete pozvati tu verziju putem prekidača u HTTP ili događajnom handleru. (Ako je ta funkcija duboko u stablu poziva, tijekom toga se stvara nova verzija svake funkcije. Čini se kao da je to prekomjerno, ali funkcije se ne miješaju ako ih ne koristite, tako da to čak ni ne primijetite.)
Iz istih razloga verzioniramo tipove. O našem sistemu tipova detaljno smo pisali .
Zahvaljujući verzioniranju funkcija i tipova možete postupno uvoditi promjene u aplikaciju. Možete provjeriti da svaki pojedini handler radi s novom verzijom, ne morate odmah unijeti sve promjene u aplikacije (ali imamo alate da to brzo učinite ako to poželite).
To je mnogo sigurnije nego potpuno implementirati sve odjednom, kako se to trenutno događa.
Nove verzije paketa i standardna biblioteka
Kada ažurirate paket u Dark, 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 pomoću prekidača.
Snimka ekrana dijela automatskog procesa u Darku koja prikazuje dvije verzije funkcije Dict::get. Dict::get_v0 vraća tip Any (od kojeg se odričemo), a Dict::get_v1 vraća tip Option.
Često pružamo novu funkciju standardne biblioteke i isključujemo stare verzije. Korisnici sa starim verzijama u kodu zadržavaju pristup njima, ali novi korisnici ih neće moći dobiti. Planiramo pružiti alate za prebacivanje korisnika sa starih verzija na nove u jednom koraku, opet uz pomoć prekidača funkcija.
Dark također pruža jedinstvenu priliku: dok izvršavamo vaš radni kod, možemo sami testirati nove verzije, uspoređujući izlaze za nove i stare zahtjeve, kako bismo vas obavijestili o promjenama. Na kraju, ažuriranje paketa, koje se često izvodi nasumično (ili zahtijeva pažljivo testiranje iz sigurnosnih razloga), predstavlja znatno manje rizika i može se odvijati automatski.
Nove verzije Dark
Prijelaz s Pythona 2 na Python 3 protegao se kroz desetljeće i još uvijek ostaje problem. Budući da kreiramo Dark za kontinuiranu isporuku, potrebno je uzeti u obzir te promjene jezika.
Kada provedemo manje promjene u jeziku, stvaramo novu verziju Dark. Stari kod ostaje u staroj verziji Dark, a novi kod se koristi u novoj verziji. Za prelazak na novu verziju Dark možete koristiti preklopnike ili verzije funkcija.
To je osobito korisno, s obzirom na to da je Dark nedavno nastao. Mnoge promjene u jeziku ili biblioteci mogu se pokazati neuspješnima. Postepeno verzioniranje jezika omogućuje nam da provodimo manje nadogradnje, odnosno možemo ne žuriti i odgoditi mnoga jezična rješenja dok ne budemo imali više korisnika, što podrazumijeva i više informacija.
Migracije baza podataka
Za sigurnu migraciju baze podataka postoji :
- Prepisati kod za podršku novim i starim formatima
- Pretvoriti sve podatke u novi format
- Ukloniti stari pristup podacima
Na kraju, migracija baze podataka se produžava i zahtijeva mnogo resursa. A mi akumuliramo zastarjele sheme, jer čak i jednostavni zadaci, poput ispravljanja imena tablice ili stupca, ne vrijede uloženih napora.
Dark ima učinkovitu platformu za migraciju baza podataka koja (nadamo se) toliko pojednostavljuje proces da ćete prestati strahovati od njega. Sva skladišta podataka u Darku (skladišta parova "ključ-vrijednost" ili trajne heš-tablice) imaju tip. Da biste premjestili skladište podataka, jednostavno mu dodijelite novi tip i funkciju povratka i napretka za pretvorbu vrijednosti između dva tipa.
Pristup podacima u Darku odvija se preko verzioniranih imena varijabli. Na primjer, spremište podataka Users prvotno će se zvati Users-v0. Kada se stvori nova verzija s drugim tipom, ime se mijenja u Users-v1. Ako su podaci spremljeni putem Users-v0, a vi im pristupate putem Users-v1, primjenjuje se funkcija vraćanja. Ako su podaci spremljeni putem Users-v1, a vi im pristupate putem Users-v0, primjenjuje se funkcija povratka.
Ekran migracije baze podataka s imenima polja stare baze podataka, izrazima vraćanja i povratka te uputama za pokretanje migracije.
Koristite prekidače značajki za usmjeravanje poziva s Users-v0 na verziju Users-v1. To možete raditi jedan HTTP handler u isto vrijeme kako biste smanjili rizike, a prekidači također djeluju za pojedinačne korisnike, tako da možete testirati da sve radi kako je očekivano. Kada korisnika Users-v0 više ne bude, Dark automatski u pozadini pretvara sve preostale podatke iz starog formata u novi. Čak to nećete ni primijetiti.
Testiranje
Dark je i nepromjenjivim vrijednostima, stoga je površina za testiranje znatno manja u usporedbi s objektno-orijentiranim jezicima s dinamičkim tipiziranjem. No, testirati se mora.
U Darku, uređivač automatski pokreće modularne testove u pozadini za uređeni kod i prema zadanim postavkama pokreće te testove za sve prekidače značajki. U budućnosti želimo automatski provoditi fuzz testing koda koristeći statičke tipove kako bismo pronašli greške.
Osim toga, Dark izvršava vašu infrastrukturu u produkciji, što otvara nove mogućnosti. Automatski pohranjujemo HTTP zahtjeve unutar Dark infrastrukture (dok trenutno pohranjujemo sve zahtjeve, no kasnije se planiramo prebaciti na uzorkovanje). Testiramo novi kod na njima i provodimo modularne testove, a ako želite, lako možete pretvoriti zanimljive zahtjeve u modularne testove.
Od čega smo se riješili
Budući da nemamo implementaciju, ali imamo prekidače značajki, oko 60% pipeline-a implementacije ostaje izvan upotrebe. Ne trebaju nam git grane ili pull requesti, izgradnja backend resursa i kontejnera, slanje resursa i kontejnera u registracije ili koraci implementacije u Kubernetes.
Usporedba standardnog kontinuiranog isporučnog lanca (slijeva) i Dark kontinuirane isporuke (sdesna). U Dark isporuci sastoji se od 6 koraka i jednog ciklusa, dok tradicionalna verzija uključuje 35 koraka i 3 ciklusa.
U Dark razvoju postoji samo 6 koraka i 1 ciklus (koraci koji se ponavljaju više puta), dok moderni kontinuirani isporučni lanac sastoji se od 35 koraka i 3 ciklusa. U Dark testovi se pokreću automatski, a vi to čak ni ne primjećujete; ovisnosti se instaliraju automatski; sve što se odnosi na git ili Github više nije potrebno; graditi, testirati i slati Docker kontejnere nije potrebno; razdeployment u Kubernetes više nije potrebno.
Čak su i preostali koraci u Dark postali lakši. Budući da se prekidačima funkcija može upravljati jednim akcijom, ne morate ponovno prolaziti kroz cijeli lanac isporuke kako biste uklonili stari kod.
Pokušali smo pojednostaviti isporuku koda, skraćujući vrijeme i rizike povezane s kontinuiranom isporukom. Također smo značajno pojednostavili ažuriranje paketa, migracije baza podataka, testiranje, upravljanje verzijama, instalaciju ovisnosti, jednakost između razvojne i produkcijske okoline i brze i sigurne nadogradnje verzija jezika.
Odgovaram na pitanja o tome na .
Da biste saznali više o Dark uređaju, pročitajte , (ili na ) ili . Ako idete na StrangeLoop u rujnu, .
Izvor: habr.com
