
Колкото по-бързо е разработването, толкова по-бързо напредва технологичната компания.
За съжаление, съвременните приложения работят срещу нас — нашите системи трябва да се обновяват в реално време, без да пречат на никого и без да водят до прекъсвания. Разгръщането в такива системи става сложна задача и изисква сложни конвейери за непрекъсната доставка дори в малки екипи.
Тези конвейери обикновено имат тесен обхват, работят бавно и не се отличават с надеждност. Разработчиците трябва първо да ги създадат ръчно, а след това да ги управляват, и компаниите често наемат цели DevOps екипи за това.
Скоростта на тези конвейери определя скоростта на разработването. При най-добрите екипи разгръщането отнема 5-10 минути, но обикновено всичко се случва много по-дълго, и за едно разгръщане са необходими няколко часа.
В Dark това отнема 50 мс. Петдесет. Милисекунди.. Dark — , създадено специално за непрекъсната доставка, и всички аспекти на Dark, включително самият език, са изградени с мисъл за безопасно мигновено разгръщане.
Защо конвейерите за непрекъсната доставка са толкова бавни?
Представете си, че имаме уеб приложение на Python и вече сме създали страхотен и модерен конвейер за непрекъсната доставка. За разработчика, който всеки ден работи по този проект, разгръщането на една малка промяна ще изглежда горе-долу така:
Внасяне на промени
- Създаване на нов клон в git
- Внасяне на промени с въртящ се превключвател
- Модулно тестване за проверка на промените с и без въртяща функция
Пул-иск
- Комитване на промените
- Изпращане на промените в отдалечен репозиторий на github
- Пул-иск
- CI се изпълнява автоматично във фонов режим
- Преглед на кода
- Още няколко прегледа, ако е необходимо
- Сливане на промените с основния git.
CI се изпълнява на основния
- Инсталиране на клиентски зависимости чрез npm
- Сглобяване и оптимизация на HTML+CSS+JS ресурсите
- Изпълнение на модулни и функционални тестове в клиентската част
- Инсталиране на зависимости на Python от PyPI
- Изпълнение на модулни и функционални тестове в сървърната част
- Интеграционно тестване и на двете страни
- Изпращане на ресурсите на клиентската част в CDN
- Сглобяване на контейнер за Python програмата.
- Изпращане на контейнер в регистъра
- Актуализация на Kubernetes манифеста
Подмяна на стар код с нов
- Kubernetes стартира няколко инстанции на новия контейнер
- Kubernetes изчаква инстанциите да станат работещи
- Kubernetes добавя инстанции в HTTP балансьора на натоварването
- Kubernetes изчаква, докато старите инстанции спрат да се използват
- Kubernetes спира старите инстанции
- Kubernetes повтаря тези операции, докато новите инстанции не заменят всички стари
Включване на новата функция
- Новият код се активира само за себе си, за да се увери, че всичко е наред
- Новият код се активира за 10% от потребителите, следят се оперативните и бизнес метрики
- Новият код се активира за 50% от потребителите, следят се оперативните и бизнес метрики
- Новият код се активира за 100% от потребителите, следят се оперативните и бизнес метрики
- Накрая повтаряте цялата процедура, за да премахнете стария код и ключа
Процесът зависи от инструментите, езика и използването на услуги, ориентирани към архитектура, но накратко изглежда така. Не споменах разгръщания с миграция на бази данни, защото за това е нужно внимателно планиране, но по-долу ще обясня как Dark се справя с това.
Има много компоненти и много от тях лесно могат да забавят, да се провалят, да предизвикат времеви конкуренции или да срина работната система.
А тъй като тези пайплайни почти винаги са създадени за специални случаи, на тях е трудно да се разчита. Много хора имат дни, когато кодът не може да бъде разгърнат, защото има проблеми в Dockerfile, един от десетките услуги е се провалил или необходимият специалист е в отпуск.
Още по-лошо, много от тези стъпки изобщо не правят нещо полезно. Те бяха нужни по-рано, когато разгръщахме кода директно за потребителите, но сега имаме ключове за нов код и тези процеси са разделени. В резултат, стъпката, на която кодът се разгръща (старият се заменя с новия), сега се е превърнала в просто излишен риск.
Разбира се, това е много обмислен пайплайн. Екипът, който го е създал, не е пестил време и средства за бързо разгръщане. Обикновено разгръщанията на пайплайни са значително по-бавни и ненадеждни.
Изпълнение на непрекъсната доставка в Dark
Непрерывната доставка е толкова важна за Dark, че още в самото начало се стремяхме към време по-малко от секунда. Прегледахме всички стъпки в пайплайна, за да отстраним всичко ненужно, а останалото го доведохме до съвършенство. Ето как премахнахме стъпките.
Джеси Фразел () изобрети нова дума „deployless“ (без необходимост от разгръщане) на конференцията Future of Software Development в Рейкявик.
Веднага решихме, че Dark ще се основава на концепцията „deployless“ (благодарение на за неологизма). Deployless означава, че всеки код моментално се разгръща и е готов за употреба в продукция. Разбира се, няма да пропуснем неизправен или непълен код (принципите на сигурност ще опиша по-долу).
По време на демонстрацията на Dark често ни питаха как успяхме да ускорим разгръщането толкова много. Странен въпрос. Хората вероятно мислят, че сме изобретили някаква супертехнология, която сравнява кода, компилира го, опакова го в контейнер, стартира виртуална машина, стартира контейнера на студено и всичко в този дух — и всичко това за 50 мс. Вероятно това е невъзможно. Но ние създадохме специален двигател за разгръщане, на който не му е необходимо всичко това.
Dark стартира интерпретатори в облака. Да кажем, че пишете код в функция или HTTP обработчик или обработчик на събития. Изпращаме diff в абстрактното синтаксично дърво (реализация на кода, която вътрешно използва нашият редактор и сървъри) на нашите сървъри, а след това стартираме този код, когато пристигнат запитвания. Така че разгръщането изглежда просто като скромно записване в база данни — мигновено и елементарно. Разгръщането протича толкова бързо, защото включва минималното необходимо.
В бъдеще планираме да направим от Dark компилатор на инфраструктура, който ще създава и стартира идеалната инфраструктура за висока производителност и надеждност на приложенията. Мигновеното разгръщане, разбира се, няма да изчезне.
Безопасно разгръщане
Структуриране на редактора
Кодът в Dark се пише в редактора Dark. Структурираният редактор не допуска синтактични грешки. Всъщност в Dark дори няма анализатор. Докато въвеждате текст, ние работим директно с абстрактното синтаксично дърво (AST), като , , , и .
Всякакъв незавършен код в Dark има допустима семантика при изпълнение, подобно на . Например, ако променяте извикването на функция, ние запазваме старата функция, докато новата не стане готова.
Всяка програма в Dark има своето значение, така че незавършеният код не пречи на завършения да работи.
Режими на редактиране
Пишете код в Dark в два случая. Първият: пишете нов код и сте единственият потребител. Например, той е в REPL и други потребители никога нямат достъп до него или това е нов HTTP маршрут, на който не се позовавате никъде. Тук можете да работите без никакви предпазни мерки, и в момента работите по подобен начин в средата за разработка.
Втората ситуация: кодът вече се използва. Ако през кода преминава трафик (функции, обработчици на събития, бази данни и подобно), трябва да бъдете внимателни. За това блокираме целия използван код и изискваме да се използват по-структурирани инструменти за неговото редактиране. За структурните инструменти ще говоря по-долу: превключватели на функции за HTTP обработчици и събития, мощна платформа за миграция за бази данни и нов метод за управление на версии за функции и типове.
Превключватели на функции
Един от начините в Dark – да се решат няколко проблема с едно решение. Превключвателите на функции изпълняват много различни задачи: замяна на местната среда за разработка, git клониране, разпространение на код и, разбира се, традиционно бавно и контролирано пускане на нов код.
Създаването и разпространението на превключвател на функция се извършва в нашия редактор в една операция. Той създава празно пространство за нов код и предоставя контроли за достъп до стария и новия код, както и бутони и команди за постепенно преминаване към новия код или неговото изключване.
Превключвателите на функции са вградени в езика Dark, а дори и незавършените превключватели изпълняват своята задача – ако условието в превключвателя не е изпълнено, ще се изпълнява старият блокиран код.
Среда за разработка
Функционалните превключватели заменят локалната среда за разработка. Днес е трудно на екипите да се следи, че всички използват еднакви версии на инструментите и библиотеките (инструменти за форматиране на код, линтери, мениджъри на пакети, компилатори, препроцессори, инструменти за тестове и т.н.). С Dark не е нужно да инсталирате зависимости локално, да управлявате локалната инсталация на Docker или да предприемате други мерки, за да осигурите поне мъничко равенство между средата за разработка и продукцията. , дори няма да се преструваме, че се стремим към него.
Вместо да създаваме клонирана локална среда, превключвателите в Dark създават нов пясъчник в продукцията, който заменя средата за разработка. В бъдеще планираме да създаваме пясъчник за други части на приложението (например мигновени клони на базата данни), макар че в момента това не изглежда толкова важно.
Клонове и разгръщания
В момента има няколко начина за въвеждане на нов код в системите: git клонове, етапи на разгръщане и функционални превключватели. Те решават един и същи проблем в различни части на работния процес: git — на етапите преди разгръщането, разгръщането — в момента на преминаване от стар код към нов, а функционалните превключватели — за контролирано пускане на нов код.
Най-ефективният начин са функционалните превключватели (освен това, най-лесният за разбиране и използване). С тях можете напълно да се откажете от другите два метода. Особено полезно е да премахнете разгръщанията — ако все пак използваме функционални превключватели, за да активираме кода, то стъпката за мигновено преминаване на сървърите към новия код само създава излишни рискове.
Git е труден за използване, особено за начинаещи, и това много го ограничава, но има удобни клонове. Ние потиснахме много недостатъци на git. Dark предлага редактиране в реално време и възможност за сътрудничество по подобие на Google Документи, за да не се налага да изпращате код и да се налага да правите ребазиране и сливания по-рядко.
Функционалните преки слайдове са основата на безопасното разгръщане. Заедно с мигновените разгръщания, те позволяват бързо тестване на концепции в малки фрагменти с нисък риск, вместо да се прилагат едно голямо изменение, което може да срине системата.
Версиониране
За промените на функции и типове използваме версиониране. Ако искате да промените функция, Dark създава нова версия на тази функция. След това можете да извикате тази версия с помощта на прекъсвач в HTTP или събитийния обработчик. (Ако функцията е дълбоко вложена в графа на извикванията, по време на извикването се създава нова версия за всяка функция. Може да изглежда излишно, но функциите не пречат, ако не ги използвате, така че дори няма да го забележите.)
По същите причини версионираме и типове. Подробно сме говорили за нашата система за типове .
Благодарение на версионирането на функциите и типовете можете постепенно да вносите промени в приложението. Можете да проверите дали всеки отделен обработчик работи с новата версия, без да е необходимо веднага да прилагате всички промени в приложенията (но разполагаме с инструменти, за да го направим бързо, ако решите).
Това е много по-безопасно, отколкото пълното разгръщане наведнъж, както се случва в момента.
Нови версии на пакети и стандартната библиотека
Когато обновявате пакет в Dark, ние не заменяме веднага използването на всяка функция или тип в целия код. Това не е безопасно. Кодът продължава да използва същата версия, която е използвал, а вие обновявате използването на функциите и типовете до новата версия за всеки отделен случай с помощта на прекъсвачите.
Скрийншот на част от автоматичния процес в Dark, показващ две версии на функцията Dict::get. Dict::get_v0 връщаше тип Any (от който се отказваме), а Dict::get_v1 връща тип Option.
Често предоставяме нова функция в стандартната библиотека и изключваме старите версии. Потребителите с по-стари версии в кода ще имат достъп до тях, но новите потребители няма да могат да ги получат. Планираме да предоставим инструменти за прехвърляне на потребители от старите версии на новите с 1 стъпка, и отново с помощта на прекъсвачите на функции.
Dark предлагаща уникална възможност: тъй като изпълняваме вашия работен код, можем сами да тестваме новите версии, сравнявайки изходните данни за нови и стари заявки, за да ви известим за промените. В резултат, обновлението на пакетите, което често се извършва сляпо (или изисква обстойно тестване за сигурност), представлява много по-ниски рискове и може да се осъществи автоматично.
Нови версии на Dark
Преходът от Python 2 на Python 3 продължи десетилетие и все още остава проблем. Тъй като създаваме Dark за непрекъсната доставка, трябва да се вземат предвид тези промени в езика.
Когато внасяме малки промени в езика, създаваме нова версия на Dark. Старият код остава в старата версия на Dark, а новият код се използва в новата версия. За преход към новата версия на Dark могат да се използват превключватели или версии на функции.
Това е особено полезно, като се вземе предвид, че Dark се появи съвсем наскоро. Много промени в езика или библиотеката могат да се окажат неуспешни. Постепенното версиониране на езика ни позволява да правим незначителни актуализации, т.е. можем да не бързаме и да отложим много решения относно езика, докато нямаме повече потребители, а следователно и повече информация.
Миграции на бази данни
За безопасна миграция на база данни съществува :
- Пренаписване на кода за поддръжка на нови и стари формати
- Превръщане на всички данни в нов формат
- Премахване на стария достъп до данни
В резултат, миграцията на базата данни се проточва и изисква много ресурси. И с времето натрупваме остарели схеми, тъй като дори простите задачи, като коригиране на името на таблица или колона, не си заслужават усилията.
Dark разполага с ефективна платформа за миграция на бази данни, която (надяваме се) да опрости процеса до такава степен, че да спрете да се страхувате от него. Всички хранилища на данни в Dark (хранилища на двойки "ключ-стойност" или постоянни хеш-таблици) имат тип. За да преместите хранилището данни, просто му задавате нов тип и функция за обратна и напреднала трансформация на стойностите между двата типа.
Достъпът до хранилищата данни в Dark се осъществява чрез версионирани имена на променливи. Например, хранилището данни Users първоначално ще се нарича Users-v0. Когато се създаде нова версия с различен тип, името се променя на Users-v1. Ако данните са запазени чрез Users-v0, а вие се обръщате към тях чрез Users-v1, се прилага функция за въртение. Ако данните са запазени чрез Users-v1, а вие се обръщате към тях чрез Users-v0, се прилага функция за откат.
Екранът за миграция на базата данни с имената на полетата от старата база данни, изразите за въртение и откат и инструкциите за включване на миграцията.
Използвайте превключватели на функции, за да насочите повикванията към Users-v0 в версия Users-v1. Това може да се прави по един HTTP обработчик наведнъж, за да се намалят рисковете, а освен това превключвателите работят за отделни потребители, така че можете да тествате дали всичко работи, както се очаква. Когато потребителите на Users-v0 свършат, Dark ще трансформира всичките останали данни в фонов режим от стария формат в новия. Вие дори няма да забележите.
Тестване
Dark е и неизменяеми стойности, така че повърхността за тестване му е значително по-малка в сравнение с обектно-ориентираните езици с динамична типизация. Но тестването е все пак необходимо.
В Dark редакторът автоматично стартира модулни тестове в фонов режим за редактирания код и по подразбиране изпълнява тези тестове за всички превключватели на функции. В бъдеще искаме чрез статични типове автоматично да извършваме фаззинг на кода, за да откриваме бъгове.
Освен това, Dark изпълнява вашата инфраструктура в продуктивна среда, което отваря нови възможности. Ние автоматично съхраняваме HTTP заявки в инфраструктурата на Dark (докато в момента запазваме всички заявки, но впоследствие искаме да преминем на проба). Ние тестваме новия код по тях и провеждаме модулни тестове, и ако желаете, можете лесно да преобразувате интересни заявки в модулни тестове.
От какво се освободихме
Тъй като нямаме разгръщане, но имаме превключватели на функции, около 60% от конвейера за разгръщане остава извън борда. Не ни трябват git клонове или пул заявки, изграждане на бекенд ресурси и контейнери, изпращане на ресурси и контейнери в регистри или стъпки за разгръщане в Kubernetes.
Сравнение на стандартния пайплайн за непрекъсната доставка (вляво) и непрекъсната доставка Dark (вдясно). В Dark доставката се състои от 6 стъпки и един цикъл, докато традиционната версия включва 35 стъпки и 3 цикъла.
В Dark има само 6 стъпки и 1 цикъл (стъпките, които се повтарят няколко пъти), докато съвременният пайплайн за непрекъсната доставка се състои от 35 стъпки и 3 цикъла. В Dark тестовете се стартират автоматично, и вие дори не ги виждате; зависимостите се инсталират автоматично; всичко, свързано с git или Github, вече не е нужно; не е необходимо да се събират, тестват и изпращат Docker контейнери; разгръщането в Kubernetes вече не е необходимо.
Дори останалите стъпки в Dark станаха по-прости. Тъй като превключвателите на функциите могат да се контролират с едно действие, не е необходимо да преминавате отново през целия пайплайн за разгръщане, за да премахнете стария код.
Ние опростихме доставката на код, като намалихме времето и рисковете на непрекъснатата доставка. Освен това значително опростихме актуализацията на пакети, миграцията на бази данни, тестването, управлението на версиите, инсталирането на зависимости, равенството между средата за разработка и продукция и бързите и безопасни актуализации на версиите на езика.
Отговарям на въпроси относно това на .
За да научите повече за устройството Dark, прочетете , (или за ) или . Ако отивате на StrangeLoop през септември, .
Източник: habr.com
