{"id":36721,"date":"2019-10-31T22:13:20","date_gmt":"2019-10-31T19:13:20","guid":{"rendered":"https:\/\/prohoster.info\/blog\/kak-dark-razvertyvaet-kod-za-50-ms\/"},"modified":"2019-10-31T22:13:20","modified_gmt":"2019-10-31T19:13:20","slug":"kak-dark-razvertyvaet-kod-za-50-ms","status":"publish","type":"post","link":"https:\/\/prohoster.info\/no\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","title":{"rendered":"Hvordan Dark distribuerer kode p\u00e5 50 ms","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p><img decoding=\"async\" alt=\"Hvordan Dark distribuerer kode p\u00e5 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/c159a36eb52bf488f3a70ea511690366.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/p>\n<p><\/p>\n<p>Jo raskere utviklingsprosessen er, jo raskere utvikler teknologi-selskapet seg.<\/p>\n<p><\/p>\n<p>Dessverre jobber moderne applikasjoner mot oss \u2014 systemene v\u00e5re m\u00e5 oppdateres i sanntid uten \u00e5 forstyrre noen eller for\u00e5rsake nedetid. Distribusjon i slike systemer blir en komplisert oppgave og krever komplekse pipeliner for kontinuerlig levering selv i sm\u00e5 team.<\/p>\n<p><\/p>\n<p>Disse pipeline-ene har vanligvis smal anvendelse, fungerer sakte og er ikke p\u00e5litelige. Utviklere m\u00e5 f\u00f8rst opprette dem manuelt, og deretter administrere dem; ofte ansetter selskapene hele DevOps-team for dette.<\/p>\n<p><\/p>\n<p>Hastigheten til disse pipeline-ene avgj\u00f8r hastigheten p\u00e5 utviklingen. For de beste teamene tar distribusjon 5\u201310 minutter, men vanligvis tar det mye lenger tid, og for en enkelt distribusjon kreves det flere timer.<\/p>\n<p><noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><\/p>\n<p>I Dark tar dette 50 ms. <em>Femtio. Millisekund.<\/em>. Dark \u2014 <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">er en omfattende l\u00f8sning med programmeringsspr\u00e5k, editor og infrastruktur<\/a><\/noindex>, skapt spesielt for kontinuerlig levering, og alle aspekter av Dark, inkludert selve spr\u00e5ket, er bygget med tanke p\u00e5 sikker, \u00f8yeblikkelig distribusjon.<\/p>\n<p><\/p>\n<h3 id=\"pochemu-konveyery-nepreryvnoy-postavki-takie-medlennye\">Hvorfor er pipeliner for kontinuerlig levering s\u00e5 trege?<\/h3>\n<p><\/p>\n<p>La oss si at vi har en Python webapplikasjon og vi allerede har laget en fantastisk og moderne pipeline for kontinuerlig levering. For utvikleren som jobber med dette prosjektet hver dag, vil distribusjon av en liten endring se omtrent slik ut:<\/p>\n<p><\/p>\n<h3 id=\"vnesenie-izmeneniy\">Gj\u00f8re endringer<\/h3>\n<p><\/p>\n<ul>\n<li>Opprette en ny gren i git<\/li>\n<li>Gj\u00f8re endringer bak funksjonsbryteren<\/li>\n<li>Modul\u00e6rt testing for \u00e5 sjekke endringer med og uten funksjonsbryteren<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"pul-rekvest\">Pull-foresp\u00f8rsel<\/h3>\n<p><\/p>\n<ul>\n<li>Committe endringer<\/li>\n<li>Push endringer til den eksterne lagringsplassen p\u00e5 github<\/li>\n<li>Pull-foresp\u00f8rsel<\/li>\n<li>CI bygget utf\u00f8res automatisk i bakgrunnen<\/li>\n<li>Kodegjennomgang<\/li>\n<li>Noen flere vurderinger, om n\u00f8dvendig<\/li>\n<li>Sl\u00e5 sammen endringer med master i git.<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"ci-vypolnyaetsya-na-mastere\">CI kj\u00f8rer p\u00e5 master<\/h3>\n<p><\/p>\n<ul>\n<li>Installere frontend-avhengigheter via npm<\/li>\n<li>Bygge og optimalisere HTML+CSS+JS ressurser<\/li>\n<li>Kj\u00f8re modul- og funksjonstester p\u00e5 frontend<\/li>\n<li>Installere Python-avhengigheter fra PyPI<\/li>\n<li>Kj\u00f8re modul- og funksjonstester p\u00e5 backend<\/li>\n<li>Integrasjonstesting p\u00e5 begge ender<\/li>\n<li>Push frontend-ressurser til CDN<\/li>\n<li>Bygge container for Python-programmet<\/li>\n<li>Sending the container to the registry<\/li>\n<li>Updating the Kubernetes manifest<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"zamena-starogo-koda-novym\">Replacing old code with new<\/h3>\n<p><\/p>\n<ul>\n<li>Kubernetes launches multiple instances of the new container<\/li>\n<li>Kubernetes waits for the instances to become operational<\/li>\n<li>Kubernetes adds instances to the HTTP load balancer<\/li>\n<li>Kubernetes waits for the old instances to stop being used<\/li>\n<li>Kubernetes stops the old instances<\/li>\n<li>Kubernetes repeats these operations until the new instances replace all old ones<\/li>\n<\/ul>\n<p><\/p>\n<h3 id=\"vklyuchenie-novogo-pereklyuchatelya-funkcii\">Enabling the new feature switch<\/h3>\n<p><\/p>\n<ul>\n<li>The new code is enabled only for itself to ensure everything is fine<\/li>\n<li>The new code is enabled for 10% of users, operational and business metrics are tracked<\/li>\n<li>The new code is enabled for 50% of users, operational and business metrics are tracked<\/li>\n<li>The new code is enabled for 100% of users, operational and business metrics are tracked<\/li>\n<li>Finally, you repeat the entire procedure to remove the old code and switch<\/li>\n<\/ul>\n<p><\/p>\n<p>The process depends on the tools, language, and service-oriented architecture used, but generally looks like this. I didn't mention deployments with database migrations because they require careful planning, but below I will explain how Dark handles that.<\/p>\n<p><\/p>\n<p>There are many components here, and many of them can easily throttle, crash, cause temporary contention, or bring down the working system.<\/p>\n<p><\/p>\n<p>And since these pipelines are almost always created for a specific case, they are hard to rely on. Many have days when the code cannot be deployed because there are issues in the Dockerfile, one of dozens of services has crashed, or the necessary specialist is on vacation.<\/p>\n<p><\/p>\n<p>Worse yet, many of these steps don't do anything useful at all. They were needed before when we deployed code directly for users, but now we have switches for new code, and these processes have split. As a result, the step where the code is deployed (old is replaced with new) has now become just an unnecessary risk.<\/p>\n<p><\/p>\n<p>Of course, this is a very thoughtful pipeline. The team that created it did not spare time and money for quick deployment. Typically, deployment pipelines are much slower and less reliable.<\/p>\n<p><\/p>\n<h3 id=\"realizaciya-nepreryvnoy-postavki-v-dark\">Implementing continuous delivery in Dark<\/h3>\n<p><\/p>\n<p>Den kontinuerlige leveransen er s\u00e5 viktig for Dark at vi fra starten av hadde som m\u00e5l \u00e5 bruke mindre enn ett sekund. Vi har g\u00e5tt gjennom alle trinnene i pipeline for \u00e5 eliminere alt un\u00f8dvendig, og perfeksjonert det som gjensto. Slik har vi fjernet trinnene.<\/p>\n<p><\/p>\n<blockquote><p>Jessie Frazelle (<noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/jessfraz\">Jessie Frazelle<\/a><\/noindex>) fant opp det nye ordet deployless (uten behov for distribusjon) under konferansen Future of Software Development i Reykjavik.<\/p><\/blockquote>\n<p>Vi bestemte oss umiddelbart for at Dark skulle v\u00e6re basert p\u00e5 konseptet \"deployless\" (takk til <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/jessfraz\">Jessie Frazelle<\/a><\/noindex> for neologismen). Deployless betyr at enhver kode distribueres umiddelbart og er klar for produksjon. Selvf\u00f8lgelig vil vi ikke slippe gjennom feil eller ufullstendig kode (jeg vil beskrive sikkerhetsprinsippene nedenfor).<\/p>\n<p><\/p>\n<p>Under demonstrasjonen av Dark ble vi ofte spurt hvordan vi klarte \u00e5 akselerere utrullingen s\u00e5 mye. Merkelig sp\u00f8rsm\u00e5l. Folk tror kanskje vi har utviklet noen superteknologi som sammenligner kode, kompilere den, pakker den inn i en container, kj\u00f8rer en virtuell maskin, starter containeren kaldt og alt det der \u2013 alt dette p\u00e5 50 ms. Det er det lite sannsynlig at vi kan. Men vi har laget en spesialutviklet distribusjonsmotor som ikke har bruk for det.<\/p>\n<p><\/p>\n<p>Dark kj\u00f8rer tolker i skyen. La oss si at du skriver kode i en funksjon eller en HTTP- eller hendelsesbehandler. Vi sender diffs til et abstrakt syntakstr\u00e6r (implementeringen av koden som internt brukes av v\u00e5r editor og servere) til v\u00e5re servere, og s\u00e5 kj\u00f8rer vi denne koden n\u00e5r foresp\u00f8rslene kommer inn. S\u00e5 distribusjonen ser bare ut som en beskjeden oppf\u00f8ring i en database \u2013 \u00f8yeblikkelig og element\u00e6r. Distribusjonen skjer s\u00e5 raskt fordi den inkluderer det aller minste.<\/p>\n<p><\/p>\n<p>I fremtiden planlegger vi \u00e5 gj\u00f8re av Dark til en infrastrukturkompilator som vil bygge og kj\u00f8re den ideelle infrastrukturen for h\u00f8y ytelse og p\u00e5litelighet av applikasjoner. \u00d8yeblikkelig distribusjon, selvf\u00f8lgelig, vil ikke g\u00e5 bort.<\/p>\n<p><\/p>\n<h2 id=\"bezopasnoe-razvertyvanie\">Sikker distribusjon<\/h2>\n<p><\/p>\n<h3 id=\"strukturirovannyy-redaktor\">Strukturert editor<\/h3>\n<p><\/p>\n<p>Koden i Dark skrives i Dark-editoren. Den strukturerte editoren tillater ikke syntaksfeil. I bunn og grunn har Dark ikke engang en parser. Mens du taster inn tekst, jobber vi direkte med det abstrakte syntakstr\u00e6r (AST), som <noindex><a rel=\"nofollow\" href=\"http:\/\/danmidwood.com\/content\/2014\/11\/21\/animated-paredit.html\">Paredit<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/ravichugh.github.io\/sketch-n-sketch\/\">Sketch-n-Sketch<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/gregoor.github.io\/tofu\/\">Tofu<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/www.facebook.com\/notes\/kent-beck\/prune-a-code-editor-that-is-not-a-text-editor\/1012061842160013\/\">Prune<\/a><\/noindex> og <noindex><a rel=\"nofollow\" href=\"https:\/\/www.jetbrains.com\/mps\/\">MPS<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Hver ufullstendig kode i Dark har en gyldig semantikk for utf\u00f8relse, omtrent som <noindex><a rel=\"nofollow\" href=\"https:\/\/hazel.org\/\">typed holes i Hazel<\/a><\/noindex>. For example, if you change a function call, we keep the old function until the new one becomes suitable.<\/p>\n<p><\/p>\n<p>Every program in Dark has its own purpose, so incomplete code does not interfere with completed code.<\/p>\n<p><\/p>\n<h3 id=\"rezhimy-redaktirovaniya\">Editing Modes<\/h3>\n<p><\/p>\n<p>You write code in Dark in two situations. First: you write new code and are the only user. For example, it is in REPL, and other users will never have access to it, or it is a new HTTP route that you do not reference anywhere. Here, you can work without any precautions, and right now you are doing just that in the development environment.<\/p>\n<p><\/p>\n<p>The second situation: the code is already in use. If traffic is passing through the code (functions, event handlers, databases, etc.), caution is required. For this, we block all used code and require more structured tools for editing it. I will explain about structured tools below: function switches for HTTP and event handlers, a powerful migration platform for databases, and a new version control method for functions and types.<\/p>\n<p><\/p>\n<h3 id=\"pereklyuchateli-funkciy\">Function Switches<\/h3>\n<p><\/p>\n<p>One way <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">to remove unnecessary complexity<\/a><\/noindex> in Dark is to solve multiple problems with one solution. Function switches perform many different tasks: replacing local development environments, git branches, code deployment, and of course, the traditional slow and controlled release of new code.<\/p>\n<p><\/p>\n<p>Creating and deploying a function switch is done in our editor in one operation. It creates an empty space for new code and provides access controls to old and new code, as well as buttons and commands for gradually transitioning to the new code or excluding it.<\/p>\n<p><\/p>\n<p>Function switches are integrated into the Dark language, and even incomplete switches perform their task \u2014 if the condition in the switch is not met, the old blocked code will execute.<\/p>\n<p><\/p>\n<h3 id=\"sreda-razrabotki\">Development Environment<\/h3>\n<p><\/p>\n<p>Funksjonsbrytere erstatter det lokale utviklingsmilj\u00f8et. I dag er det vanskelig for team \u00e5 s\u00f8rge for at alle bruker de samme versjonene av verkt\u00f8y og biblioteker (som kodeformateringsverkt\u00f8y, linters, pakkebehandlere, kompilatorer, preprosessorer, testverkt\u00f8y, osv.). Med Dark trenger man ikke \u00e5 installere avhengigheter lokalt, h\u00e5ndtere lokal Docker-installasjon eller ta andre tiltak for \u00e5 sikre en viss likhet mellom utviklingsmilj\u00f8et og produksjonen. <noindex><a rel=\"nofollow\" href=\"https:\/\/thenewstack.io\/honeycombs-charity-majors-go-ahead-test-in-production\/\">Gitt at en slik likhet fremdeles er umulig<\/a><\/noindex>, vil vi ikke engang late som vi streber etter det.<\/p>\n<p><\/p>\n<p>I stedet for \u00e5 skape et klonet lokalt milj\u00f8, skaper bryterne i Dark en ny sandkasse i produksjonen som erstatter utviklingsmilj\u00f8et. I fremtiden planlegger vi ogs\u00e5 \u00e5 lage sandkasser for andre deler av applikasjonen (for eksempel umiddelbare kloner av databasen), selv om det for n\u00e5 ikke virker s\u00e5 viktig.<\/p>\n<p><\/p>\n<h3 id=\"vetki-i-razvertyvaniya\">Grener og distribusjoner<\/h3>\n<p><\/p>\n<p>Det finnes for \u00f8yeblikket flere m\u00e5ter \u00e5 legge inn ny kode i systemene: git-grener, distribusjonsfaser og funksjonsbrytere. De l\u00f8ser ett problem i forskjellige deler av arbeidsflyten: git \u2013 p\u00e5 trinn f\u00f8r distribusjonen, distribusjon \u2013 i overgangen fra gammel kode til ny, og funksjonsbrytere \u2013 for kontrollert utgivelse av ny kode.<\/p>\n<p><\/p>\n<p>Den mest effektive metoden er funksjonsbrytere (som ogs\u00e5 er den enkleste \u00e5 forst\u00e5 og bruke). Med dem kan man helt unng\u00e5 de to andre metodene. Det er spesielt nyttig \u00e5 fjerne distribusjon \u2013 dersom vi uansett bruker funksjonsbrytere for \u00e5 aktivere koden, vil trinnet med \u00e5 oppdatere serverne til ny kode bare skape un\u00f8dvendige risikoer.<\/p>\n<p><\/p>\n<p>Git kan v\u00e6re vanskelig \u00e5 bruke, spesielt for nybegynnere, og det begrenser bruken kraftig, men det har praktiske grener. Vi har jevnet ut mange av manglene med git. Dark redigeres i sanntid og gir mulighet for samarbeid i stil med Google Dokumenter, s\u00e5 man slipper \u00e5 sende kode og kan gj\u00f8re rebasing og sammensl\u00e5ing sjeldnere.<\/p>\n<p><\/p>\n<p>Funksjonsbryterne er grunnlaget for sikker distribusjon. Sammen med \u00f8yeblikkelig distribusjon gj\u00f8r de det mulig \u00e5 teste konsepter raskt i sm\u00e5 biter med lav risiko i stedet for \u00e5 implementere en stor endring som kan krasje systemet.<\/p>\n<p><\/p>\n<h3 id=\"versionirovanie\">Versjonering<\/h3>\n<p><\/p>\n<p>For \u00e5 endre funksjoner og typer bruker vi versjonering. Hvis du \u00f8nsker \u00e5 endre en funksjon, oppretter Dark en ny versjon av denne funksjonen. Deretter kan du kalle denne versjonen med en bryter i HTTP-h\u00e5ndtereren eller hendelser. (Hvis det er en funksjon dypt i anropsgrafen, opprettes det automatisk en ny versjon av hver funksjon underveis. Det kan virke overdrevet, men funksjoner blandes ikke hvis de ikke brukes, s\u00e5 du legger ikke merke til det engang.)<\/p>\n<p><\/p>\n<p>Av de samme grunnene versjonerer vi typer. Vi har gitt en detaljert gjennomgang av typen v\u00e5rt. <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/real-problems-with-functional-languages-efe668c5264a\">i det forrige innlegget<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Takket v\u00e6re versjonering av funksjoner og typer kan du gj\u00f8re endringer i applikasjonen gradvis. Du kan sjekke at hver enkelt h\u00e5ndterer fungerer med den nye versjonen, uten \u00e5 m\u00e5tte gj\u00f8re alle endringene i applikasjonene samtidig (men vi har verkt\u00f8y for \u00e5 gj\u00f8re det raskt hvis du vil).<\/p>\n<p><\/p>\n<p>Dette er mye tryggere enn \u00e5 distribuere alt samtidig, slik det gj\u00f8res n\u00e5.<\/p>\n<p><\/p>\n<h3 id=\"novye-versii-paketov-i-standartnaya-biblioteka\">Nye versjoner av pakker og standardbiblioteket<\/h3>\n<p><\/p>\n<p>N\u00e5r du oppdaterer en pakke i Dark, erstatter vi ikke umiddelbart bruken av hver funksjon eller type i hele kodebasen. Det er usikkert. Koden fortsetter \u00e5 bruke den samme versjonen som den brukte, mens du oppdaterer bruken av funksjoner og typer til den nye versjonen for hvert enkelt tilfelle med bryterne.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/rh\/t3\/4w\/rht34wyibolrgracbz88tnqqhg0.png\"><img decoding=\"async\" alt=\"Hvordan Dark distribuerer kode p\u00e5 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/54fdb566b4bcbc10e06e51c47a3820f0.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Skjermbilde av en del av den automatiske prosessen i Dark, som viser to versjoner av funksjonen Dict::get. Dict::get_v0 returnerte typen Any (som vi g\u00e5r bort fra), mens Dict::get_v1 returnerer typen Option.<\/em><\/p>\n<p><\/p>\n<p>Vi tilbyr ofte en ny funksjon i standardbiblioteket og ekskluderer gamle versjoner. Brukere med eldre versjoner i koden vil fortsatt ha tilgang til dem, men nye brukere vil ikke kunne f\u00e5 dem. Vi planlegger \u00e5 tilby verkt\u00f8y for \u00e5 hjelpe brukere fra gamle versjoner til nye i ett trinn, ogs\u00e5 med funksjonsbrytere.<\/p>\n<p><\/p>\n<p>Dark gir deg ogs\u00e5 en unik mulighet: siden vi kj\u00f8rer koden din, kan vi selv teste nye versjoner ved \u00e5 sammenligne utdataene for nye og gamle foresp\u00f8rselene for \u00e5 informere deg om endringene. Som et resultat medf\u00f8rer oppdateringer av pakker, som ofte gj\u00f8res i blinde (eller krever grundig testing av sikkerhetshensyn), langt f\u00e6rre risikoer og kan skje automatisk.<\/p>\n<p><\/p>\n<h3 id=\"novye-versii-dark\">Nye versjoner av Dark<\/h3>\n<p><\/p>\n<p>Overgangen fra Python 2 til Python 3 strakte seg over et ti\u00e5r og er fortsatt et problem. Siden vi utvikler Dark for kontinuerlig leveranse, m\u00e5 vi ta hensyn til disse spr\u00e5kendringene.<\/p>\n<p><\/p>\n<p>N\u00e5r vi gj\u00f8r sm\u00e5 endringer i spr\u00e5ket, lager vi en ny versjon av Dark. Gammel kode forblir i den gamle versjonen av Dark, mens ny kode brukes i den nye versjonen. For \u00e5 g\u00e5 over til den nye versjonen av Dark kan man bruke brytere eller funksjonsversjoner.<\/p>\n<p><\/p>\n<p>Dette er spesielt nyttig, gitt at Dark er relativt nytt. Mange endringer i spr\u00e5ket eller biblioteket kan vise seg \u00e5 v\u00e6re mislykkede. Gradvis versjonering av spr\u00e5ket lar oss gj\u00f8re mindre oppdateringer, noe som betyr at vi kan ta oss tid og utsette mange beslutninger om spr\u00e5ket til vi har flere brukere, som igjen gir oss mer informasjon.<\/p>\n<p><\/p>\n<h3 id=\"migracii-baz-dannyh\">Databasemigrasjoner<\/h3>\n<p><\/p>\n<p>For sikker migrering av databaser finnes det <noindex><a rel=\"nofollow\" href=\"http:\/\/www.brunton-spall.co.uk\/post\/2014\/05\/06\/database-migrations-done-right\/\">en standardformel<\/a><\/noindex>:<\/p>\n<p><\/p>\n<ul>\n<li>Skrive om kode for \u00e5 st\u00f8tte b\u00e5de nye og gamle formater<\/li>\n<li>Konvertere alle data til det nye formatet<\/li>\n<li>Fjerne gammel tilgang til data<\/li>\n<\/ul>\n<p><\/p>\n<p>Som et resultat tar databasemigreringen tid og krever mye ressurser. Og vi samler opp utdaterte skjemaer, siden selv enkle oppgaver, som \u00e5 endre navnet p\u00e5 en tabell eller kolonne, ikke er verdt innsatsen.<\/p>\n<p><\/p>\n<p>Dark har en effektiv plattform for databasemigrasjon som (vi h\u00e5per) vil forenkle prosessen s\u00e5 mye at du slutter \u00e5 v\u00e6re redd for den. Alle datalagre i Dark (lagre av \"n\u00f8kkel-verdi\" eller permanente hash-tabeller) har en type. For \u00e5 overf\u00f8re et datalager tilordner du det ganske enkelt en ny type og en tilbakestillings- og rullefunksjon for \u00e5 konvertere verdiene mellom de to typene.<\/p>\n<p><\/p>\n<p>Tilgang til datalagring i Dark skjer via versjonerte variabelnavn. For eksempel vil datalageret Users opprinnelig bli kalt Users-v0. N\u00e5r en ny versjon med en annen type opprettes, endres navnet til Users-v1. Hvis data er lagret via Users-v0, men du henvender deg til dem via Users-v1, brukes rollback-funksjonen. Hvis data er lagret via Users-v1, men du henvender deg til dem via Users-v0, brukes rollback-funksjonen.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/ui\/sl\/wd\/uislwdrfrvact0d1ts5icnk-4ka.png\"><img decoding=\"async\" alt=\"Hvordan Dark distribuerer kode p\u00e5 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/35743ba246f327ca9e8b71f0069a3800.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Skjerm for migrering av databasene med navnene p\u00e5 feltene fra den gamle databasen, uttrykk for rollback og instruksjoner for \u00e5 aktivere migreringen.<\/em><\/p>\n<p><\/p>\n<p>Bruk funksjonsbrytere for \u00e5 dirigere kall fra Users-v0 til versjonen Users-v1. Dette kan gj\u00f8res en HTTP-behandler om gangen for \u00e5 redusere risikoene, og bryterne fungerer ogs\u00e5 for enkeltbrukere, slik at du kan sjekke at alt fungerer som forventet. N\u00e5r det ikke er flere brukere av Users-v0, konverterer Dark alle gjenv\u00e6rende data i bakgrunnen fra det gamle formatet til det nye. Du vil knapt merke det.<\/p>\n<p><\/p>\n<h3 id=\"testirovanie\">Testing<\/h3>\n<p><\/p>\n<p>Dark er en <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/real-problems-with-functional-languages-efe668c5264a\">funksjonell programmeringsspr\u00e5k med statisk typekontroll<\/a><\/noindex> og uforanderlige verdier, s\u00e5 testoverflaten er betydelig mindre sammenlignet med objektorienterte spr\u00e5k med dynamisk typekontroll. Men testing er fortsatt n\u00f8dvendig.<br \/>\nI Dark kj\u00f8rer redakt\u00f8ren automatisk modul\u00e6re tester i bakgrunnen for den redigerte koden og kj\u00f8rer som standard disse testene for alle funksjonsbrytere. I fremtiden \u00f8nsker vi \u00e5 utf\u00f8re fuzzing av koden automatisk ved hjelp av statiske typer for \u00e5 finne feil.<\/p>\n<p><\/p>\n<p>I tillegg kj\u00f8rer Dark infrastrukturen din i produksjon, noe som \u00e5pner for nye muligheter. Vi lagrer automatisk HTTP-foresp\u00f8rslene i Dark-infrastrukturen (for n\u00e5 lagrer vi alle foresp\u00f8rslene, men senere \u00f8nsker vi \u00e5 g\u00e5 over til sampling). Vi tester ny kode basert p\u00e5 disse foresp\u00f8rslene og kj\u00f8rer modul\u00e6re tester, og hvis \u00f8nskelig kan du enkelt konvertere interessante foresp\u00f8rslene til modul\u00e6re tester.<\/p>\n<p><\/p>\n<h3 id=\"ot-chego-my-izbavilis\">Hva vi har kvittet oss med<\/h3>\n<p><\/p>\n<p>Siden vi ikke har distribusjon, men funksjonsbrytere, er cirka 60% av distribusjonsflyten ute av spill. Vi trenger ikke git-grener eller pull-foresp\u00f8rsel, bygging av backend-ressurser og containere, sending av ressurser og containere til registre eller distribusjonstrinn i Kubernetes.<\/p>\n<p><\/p>\n<p><noindex><a rel=\"nofollow\" href=\"https:\/\/habrastorage.org\/webt\/gc\/9e\/g-\/gc9eg-szouq0dtrxxr8jd6c6dyo.jpeg\"><img decoding=\"async\" alt=\"Hvordan Dark distribuerer kode p\u00e5 50 ms\" src=\"\/wp-content\/uploads\/2019\/08\/d584b13a1f91e9eef1e2e40c25e90052.jpg\" style=\"display:block;margin: 0 auto;\" \/><\/a><\/noindex><br \/>\n<em>Samanlik av standard kontinuerlig leveranse (til venstre) og kontinuerlig leveranse Dark (til h\u00f8yre). I Dark best\u00e5r leveransen av 6 trinn og 1 syklus, mens den tradisjonelle versjonen inneholder 35 trinn og 3 sykluser.<\/em><\/p>\n<p><\/p>\n<p>I Dark er det kun 6 trinn og 1 syklus (trinn som gjentas flere ganger) under utrullingen, mens den moderne kontinuerlige leveransepipen best\u00e5r av 35 trinn og 3 sykluser. I Dark kj\u00f8res tester automatisk, og du ser dem ikke engang; avhengigheter installeres automatisk; alt relatert til git eller Github er ikke lenger n\u00f8dvendig; bygge, teste og sende Docker-containere er ikke n\u00f8dvendig; utrullingen til Kubernetes er ikke lenger n\u00f8dvendig.<\/p>\n<p><\/p>\n<p>Selv de gjenv\u00e6rende trinnene i Dark har blitt enklere. Siden funksjonsbrytere kan styres med ett enkelt tiltak, er det ikke n\u00f8dvendig \u00e5 g\u00e5 gjennom hele utrullingspipen p\u00e5 nytt for \u00e5 fjerne gammel kode.<\/p>\n<p><\/p>\n<p>Vi har forenklet kodenleveransen s\u00e5 mye vi kunne, redusert tid og risiko i kontinuerlig leveranse. Vi har ogs\u00e5 betydelig forenklet oppdatering av pakker, databasemigreringer, testing, versjonsstyring, installasjon av avhengigheter, likhet mellom utviklings- og produksjonsmilj\u00f8 og raske, sikre oppgraderinger av spr\u00e5kversjoner.<\/p>\n<p><\/p>\n<p>Jeg svarer p\u00e5 sp\u00f8rsm\u00e5l om dette p\u00e5 <noindex><a rel=\"nofollow\" href=\"https:\/\/news.ycombinator.com\/item?id=20394166\">HackerNews<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>For \u00e5 l\u00e6re mer om Dark-enheten, les <noindex><a rel=\"nofollow\" href=\"https:\/\/medium.com\/darklang\/the-design-of-dark-59f5d38e52d2\">artikkelen om Dark<\/a><\/noindex>, <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/darklang?source=post_page---------------------------\">f\u00f8lg oss p\u00e5 Twitter<\/a><\/noindex> (eller p\u00e5 <noindex><a rel=\"nofollow\" href=\"https:\/\/twitter.com\/paulbiggar?source=post_page---------------------------\">meg<\/a><\/noindex>) eller <noindex><a rel=\"nofollow\" href=\"https:\/\/darklang.com\/subscribe?source=post_page---------------------------\">meld deg p\u00e5 betaversjonen og f\u00e5 varsler om kommende innlegg<\/a><\/noindex>. Hvis du skal til StrangeLoop i september, <noindex><a rel=\"nofollow\" href=\"https:\/\/darklang.com\/launch\">kom og bli med oss p\u00e5 lanseringen<\/a><\/noindex>.<\/p>\n<p>Kilde: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/company\/southbridge\/blog\/462027\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u0440\u0430\u0437\u0432\u0438\u0432\u0430\u0435\u0442\u0441\u044f \u0442\u0435\u0445\u043d\u043e\u043b\u043e\u0433\u0438\u0447\u0435\u0441\u043a\u0430\u044f \u043a\u043e\u043c\u043f\u0430\u043d\u0438\u044f. \u041a \u0441\u043e\u0436\u0430\u043b\u0435\u043d\u0438\u044e, \u0441\u043e\u0432\u0440\u0435\u043c\u0435\u043d\u043d\u044b\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u044f \u0440\u0430\u0431\u043e\u0442\u0430\u044e\u0442 \u043f\u0440\u043e\u0442\u0438\u0432 \u043d\u0430\u0441 \u2014 \u043d\u0430\u0448\u0438 \u0441\u0438\u0441\u0442\u0435\u043c\u044b \u0434\u043e\u043b\u0436\u043d\u044b \u043e\u0431\u043d\u043e\u0432\u043b\u044f\u0442\u044c\u0441\u044f \u0432 \u0440\u0435\u0436\u0438\u043c\u0435 \u0440\u0435\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0432\u0440\u0435\u043c\u0435\u043d\u0438 \u0438 \u043f\u0440\u0438 \u044d\u0442\u043e\u043c \u043d\u0438\u043a\u043e\u043c\u0443 \u043d\u0435 \u043c\u0435\u0448\u0430\u0442\u044c \u0438 \u043d\u0435 \u043f\u0440\u0438\u0432\u043e\u0434\u0438\u0442\u044c \u043a \u043f\u0440\u043e\u0441\u0442\u043e\u044f\u043c \u0438 \u043f\u0435\u0440\u0435\u0440\u044b\u0432\u0430\u043c. \u0420\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u043d\u0438\u0435 \u0432 \u0442\u0430\u043a\u0438\u0445 \u0441\u0438\u0441\u0442\u0435\u043c\u0430\u0445 \u0441\u0442\u0430\u043d\u043e\u0432\u0438\u0442\u0441\u044f \u0441\u043b\u043e\u0436\u043d\u043e\u0439 \u0437\u0430\u0434\u0430\u0447\u0435\u0439 \u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0441\u043b\u043e\u0436\u043d\u044b\u0445 \u043f\u0430\u0439\u043f\u043b\u0430\u0439\u043d\u043e\u0432 \u043d\u0435\u043f\u0440\u0435\u0440\u044b\u0432\u043d\u043e\u0439 \u043f\u043e\u0441\u0442\u0430\u0432\u043a\u0438 \u0434\u0430\u0436\u0435 \u0432 \u043c\u0430\u043b\u0435\u043d\u044c\u043a\u0438\u0445 \u043a\u043e\u043c\u0430\u043d\u0434\u0430\u0445. [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":27506,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-36721","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.5 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/no\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.5\" \/>\n\t\t<meta property=\"og:locale\" content=\"nn_NO\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u041a\u0430\u043a Dark \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u0434 \u0437\u0430 50 \u043c\u0441 | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/no\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T19:13:20+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T19:13:20+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Hvordan Dark ruller ut kode p\u00e5 50 ms | ProHoster","description":"Jo raskere utviklingsprosessen, jo raskere.","canonical_url":"https:\/\/prohoster.info\/no\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"nn_NO","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u041a\u0430\u043a Dark \u0440\u0430\u0437\u0432\u0435\u0440\u0442\u044b\u0432\u0430\u0435\u0442 \u043a\u043e\u0434 \u0437\u0430 50 \u043c\u0441 | ProHoster","og:description":"\u0427\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435 \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438, \u0442\u0435\u043c \u0431\u044b\u0441\u0442\u0440\u0435\u0435.","og:url":"https:\/\/prohoster.info\/no\/blog\/administrirovanie\/kak-dark-razvertyvaet-kod-za-50-ms","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T19:13:20+00:00","article:modified_time":"2019-10-31T19:13:20+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"36721","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-22 04:34:22","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 01:40:22","updated":"2026-01-22 04:34:22","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/posts\/36721","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/comments?post=36721"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/posts\/36721\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/media\/27506"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/media?parent=36721"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/categories?post=36721"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/no\/wp-json\/wp\/v2\/tags?post=36721"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}