How Dark wdraża kod w 50 ms

How Dark wdraża kod w 50 ms

Im szybszy proces rozwoju, tym szybciej rozwija się firma technologiczna.

Niestety nowoczesne aplikacje działają na naszą niekorzyść – nasze systemy muszą być aktualizowane na bieżąco, nie przeszkadzając nikomu i nie powodując przestojów czy przerw. Wdrożenie w takich systemach staje się wyzwaniem i wymaga złożonych procesów ciągłego dostarczania, nawet w przypadku małych zespołów.

Potoki te mają zazwyczaj wąski zakres, są powolne i zawodne. Programiści muszą najpierw zbudować je ręcznie, a następnie zarządzać nimi, a firmy często zatrudniają do tego całe zespoły DevOps.

Szybkość rozwoju zależy od szybkości tych rurociągów. Najlepsze zespoły wdrażają się w ciągu 5–10 minut, ale zwykle trwa to znacznie dłużej i wymaga kilku godzin na wdrożenie.

W ciemności zajmuje to 50 ms. Pięćdziesiąt. milisekundy. Ciemny - jest to kompletne rozwiązanie z językiem programowania, edytorem i infrastrukturą, zbudowany specjalnie z myślą o ciągłym dostarczaniu, a każdy aspekt Dark, w tym sam język, został stworzony z myślą o bezpiecznym i natychmiastowym wdrożeniu.

Dlaczego rurociągi ciągłego dostarczania są tak powolne?

Załóżmy, że mamy aplikację internetową w języku Python i stworzyliśmy już wspaniały i nowoczesny potok ciągłego dostarczania. Dla programisty, który codziennie jest zajęty tym projektem, wdrożenie jednej drobnej zmiany wyglądałoby mniej więcej tak:

Zmiana

  • Tworzenie nowej gałęzi w git
  • Dokonywanie zmian za przełącznikiem funkcji
  • Testowanie jednostkowe w celu testowania zmian z przełącznikiem funkcji i bez niego

Prośba o pociągnięcie

  • Zatwierdź zmiany
  • Wypychanie zmian do zdalnego repozytorium Github
  • Prośba o pociągnięcie
  • CI buduje się automatycznie w tle
  • Przegląd kodu
  • W razie potrzeby jeszcze kilka recenzji
  • Łączenie zmian w git master.

CI działa na masterze

  • Instalowanie zależności frontendowych poprzez npm
  • Montaż i optymalizacja zasobów HTML+CSS+JS
  • Uruchamianie testów jednostkowych i funkcjonalnych w frontendzie
  • Instalowanie zależności Pythona z PyPI
  • Uruchamianie testów jednostkowych i funkcjonalnych w backendzie
  • Testowanie integracji na obu końcach
  • Wysyłanie zasobów frontendu do CDN
  • Budowanie kontenera dla programu w języku Python
  • Złożenie kontenera do rejestru
  • Zaktualizuj manifest Kubernetes

Zastąpienie starego kodu nowym

  • Kubernetes uruchamia wiele wystąpień nowego kontenera
  • Kubernetes czeka, aż instancje staną się zdrowe
  • Kubernetes dodaje instancje do modułu równoważenia obciążenia HTTP
  • Kubernetes czeka, aż starsze instancje nie będą już używane
  • Kubernetes zatrzymuje stare instancje
  • Kubernetes powtarza te operacje, dopóki nowe instancje nie zastąpią wszystkich starych

Włączanie nowego przełącznika funkcji

  • Nowy kod jest dołączony tylko dla Ciebie, abyś mógł upewnić się, że wszystko jest w porządku
  • Nowy kod jest włączony dla 10% użytkowników, śledzone są wskaźniki operacyjne i biznesowe
  • Nowy kod jest włączony dla 50% użytkowników, śledzone są wskaźniki operacyjne i biznesowe
  • Nowy kod jest włączony dla 100% użytkowników, śledzone są wskaźniki operacyjne i biznesowe
  • Na koniec powtarzasz całą procedurę, aby usunąć stary kod i dokonać zmiany

Proces zależy od narzędzi, języka i zastosowania architektur zorientowanych na usługi, ale ogólnie wygląda to tak. Nie wspomniałem o wdrożeniach migracji baz danych, ponieważ wymagają one dużo planowania, ale poniżej pokażę, jak Dark sobie z tym radzi.

Jest tu wiele komponentów, a wiele z nich może łatwo spowolnić, ulec awarii, spowodować tymczasowe spory lub zawiesić działający system.

A ponieważ te rurociągi są prawie zawsze tworzone na specjalny przypadek, trudno na nich polegać. Wiele osób ma dni, w których nie można wdrożyć kodu, ponieważ występują problemy w pliku Dockerfile, awaria jednej z kilkudziesięciu usług lub niezbędny specjalista jest na urlopie.

Co gorsza, wiele z tych kroków w ogóle nie przynosi niczego pożytecznego. Były one potrzebne wcześniej, gdy wdrażaliśmy kod bezpośrednio u użytkowników, ale teraz mamy przełączniki dla nowego kodu i te procesy zostały rozdzielone. W rezultacie etap wdrażania kodu (starego i zastępowania go nowym) stał się po prostu niepotrzebnym ryzykiem.

Oczywiście jest to bardzo przemyślany potok. Zespół, który go stworzył, nie szczędził czasu i pieniędzy, aby szybko go wdrożyć. Zazwyczaj potoki wdrażania są znacznie wolniejsze i bardziej zawodne.

Wdrażanie ciągłego dostarczania w Dark

Ciągłe dostarczanie jest tak ważne dla Dark, że od początku dążyliśmy do uzyskania czasów poniżej sekundy. Przeszliśmy przez wszystkie etapy rurociągu, aby usunąć wszystko, co niepotrzebne, a resztę dopracowaliśmy. W ten sposób usunęliśmy stopnie.

Jesse Frazel (Jessie Frazelle) ukuł nowe słowo „bez wdrożenia” (nie wymagające wdrożenia) na konferencji Future of Software Development w Reykjaviku

Od razu zdecydowaliśmy, że Dark będzie oparty na koncepcji „bez wdrażania” (dzięki Jessego Frazela dla neologizmu). Bez wdrożenia oznacza, że ​​dowolny kod jest natychmiast wdrażany i gotowy do użycia w środowisku produkcyjnym. Oczywiście nie pozwolimy na przedostanie się uszkodzonego lub niekompletnego kodu (zasady bezpieczeństwa opiszę poniżej).

Podczas demonstracji Dark często pytano nas, jak udało nam się tak szybko wdrożyć rozwiązanie. Dziwne pytanie. Ludzie prawdopodobnie myślą, że opracowaliśmy jakąś super technologię, która porównuje kod, kompiluje go, pakuje do kontenera, uruchamia maszynę wirtualną, uruchamia kontener na zimno i tak dalej – wszystko w 50 ms. To prawie niemożliwe. Ale stworzyliśmy specjalny silnik wdrażania, który nie potrzebuje tego wszystkiego.

Dark uruchamia tłumacze w chmurze. Załóżmy, że piszesz kod w funkcji, protokole HTTP lub procedurze obsługi zdarzeń. Wysyłamy różnicę do abstrakcyjnego drzewa składni (implementacji kodu, której używają wewnętrznie nasz edytor i serwery) na nasze serwery, a następnie uruchamiamy ten kod, gdy przychodzą żądania. Wdrożenie wygląda zatem jak skromny wpis do bazy danych – natychmiastowy i elementarny. Wdrożenie jest tak szybkie, ponieważ obejmuje absolutne minimum.

W przyszłości planujemy uczynić Dark kompilatorem infrastruktury, który utworzy i uruchomi idealną infrastrukturę zapewniającą wysoką wydajność i niezawodność aplikacji. Natychmiastowe wdrożenie będzie oczywiście na porządku dziennym.

Bezpieczne wdrożenie

Edytor strukturalny

Code in Dark jest napisany w edytorze Dark. Edytor strukturalny nie pozwala na błędy składniowe. Tak naprawdę Dark nie ma nawet analizatora. Podczas pisania pracujemy bezpośrednio z abstrakcyjnym drzewem składni (AST), np Paredyt, Szkic i szkic, Tofu, Suszona śliwka и MPS.

Każdy niedokończony kod w Dark ma prawidłową semantykę wykonania, coś w rodzaju wpisał dziury w Hazel. Na przykład, jeśli zmienisz wywołanie funkcji, zachowamy starą funkcję do czasu, aż nowa będzie użyteczna.

Każdy program w Dark ma swoje znaczenie, więc niedokończony kod nie przeszkadza w działaniu ukończonego kodu.

Tryby edycji

Kod piszesz w Dark w dwóch sytuacjach. Po pierwsze: piszesz nowy kod i jesteś jedynym użytkownikiem. Na przykład znajduje się w replice REPL i inni użytkownicy nigdy nie będą mieli do niej dostępu, lub jest to nowa trasa HTTP, do której nigdzie się nie odwołujesz. Tutaj możesz pracować bez żadnych środków ostrożności, a teraz mniej więcej tak wygląda praca w środowisku programistycznym.

Druga sytuacja: kod jest już w użyciu. Jeśli przez Twój kod przechodzi ruch (funkcje, procedury obsługi zdarzeń, bazy danych, typy), musisz zachować ostrożność. Aby to zrobić, blokujemy cały używany kod i wymagamy użycia bardziej uporządkowanych narzędzi do jego edycji. Poniżej omówię narzędzia strukturalne: przełączniki funkcji dla protokołu HTTP i obsługi zdarzeń, potężną platformę migracji dla baz danych oraz nową metodę wersjonowania funkcji i typów.

Przełączniki funkcyjne

Jeden sposób usuń niepotrzebną złożoność w ciemności - rozwiąż wiele problemów za pomocą jednego rozwiązania. Przełączniki funkcji wykonują wiele różnych zadań: zastąpienie lokalnego środowiska programistycznego, gałęzie Git, wdrażanie kodu i oczywiście tradycyjne powolne i kontrolowane wydawanie nowego kodu.

Tworzenie i wdrażanie przełącznika funkcji odbywa się w jednej operacji w naszym edytorze. Tworzy białą przestrzeń dla nowego kodu i zapewnia kontrolę dostępu dla starego i nowego kodu, a także przyciski i polecenia umożliwiające stopniowe wprowadzanie lub eliminowanie nowego kodu.

Przełączniki funkcyjne są wbudowane w język Dark i nawet niekompletne przełączniki spełniają swoją rolę - jeśli warunek w przełączniku nie zostanie spełniony, zostanie wykonany stary zablokowany kod.

Środowisko deweloperskie

Przełączniki funkcji zastępują lokalne środowisko programistyczne. Obecnie zespołom trudno jest zapewnić, że wszyscy korzystają z tych samych wersji narzędzi i bibliotek (programów formatujących kod, lintersów, menedżerów pakietów, kompilatorów, preprocesorów, narzędzi testowych itp.). Dzięki Dark nie ma potrzeby instalowania zależności lokalnie, zarządzać lokalną instalacją Dockera lub podejmować inne działania, aby zapewnić przynajmniej pozory równości pomiędzy środowiskiem programistycznym i produkcyjnym. Biorąc pod uwagę, że taka równość jest nadal niemożliwa, nawet nie będziemy udawać, że do tego dążymy.

Zamiast tworzyć sklonowane środowisko lokalne, przełączniki w Dark tworzą nową produkcyjną piaskownicę, która zastępuje środowisko programistyczne. W przyszłości planujemy piaskownicę także innych części aplikacji (np. błyskawiczne klony baz danych), choć w tej chwili nie wydaje się to aż tak istotne.

Oddziały i wdrożenia

Obecnie istnieje kilka sposobów wprowadzania nowego kodu do systemów: gałęzie git, faza wdrażania i przełączanie funkcji. Rozwiązują ten sam problem w różnych częściach przepływu pracy: git na etapach przed wdrożeniem, wdrażanie w przejściu ze starego kodu do nowego i przełączniki funkcji w celu kontrolowanego uwalniania nowego kodu.

Najskuteczniejszym sposobem są przełączniki funkcyjne (jednocześnie najłatwiejsze do zrozumienia i użycia). Dzięki nim możesz całkowicie zrezygnować z dwóch pozostałych metod. Szczególnie przydatne jest usunięcie wdrożenia — jeśli i tak używamy przełączników funkcji do włączania kodu, wówczas etap migracji serwerów do nowego kodu stwarza jedynie niepotrzebne ryzyko.

Git jest trudny w użyciu, szczególnie dla początkujących i bardzo ograniczający, ale ma wygodne gałęzie. Naprawiliśmy wiele niedociągnięć gita. Dark można edytować w czasie rzeczywistym i umożliwia współpracę w stylu Dokumentów Google, dzięki czemu nie musisz przesyłać kodu i możesz rzadziej zmieniać bazę i łączyć.

Przełączniki funkcji stanowią podstawę bezpiecznego wdrożenia. W połączeniu z natychmiastowymi wdrożeniami umożliwiają szybkie testowanie koncepcji w małych fragmentach o niskim ryzyku, zamiast wprowadzać jedną dużą zmianę, która mogłaby spowodować awarię systemu.

Wersjonowanie

Wersjonowania używamy do zmiany funkcji i typów. Jeśli chcesz zmienić funkcję, Dark tworzy nową wersję tej funkcji. Następnie możesz wywołać tę wersję za pomocą przełącznika w procedurze obsługi protokołu HTTP lub zdarzenia. (Jeśli jest to funkcja głęboko w grafie wywołań, po drodze tworzona jest nowa wersja każdej funkcji. Może się to wydawać przesadą, ale funkcje nie będą przeszkadzać, chyba że ich użyjesz, więc nawet nie będziesz ogłoszenie.)

Z tych samych powodów wersjonujemy typy. Rozmawialiśmy szczegółowo o naszym systemie typów w poprzednim poście.

Wersjonując funkcje i typy, możesz stopniowo wprowadzać zmiany w aplikacji. Możesz sprawdzić, czy każdy indywidualny moduł obsługi działa z nową wersją, bez konieczności wprowadzania wszystkich zmian w aplikacjach na raz (ale mamy narzędzia, które pozwalają to szybko zrobić, jeśli chcesz).

Jest to o wiele bezpieczniejsze niż całkowite wdrożenie wszystkiego na raz, jak ma to miejsce obecnie.

Nowe wersje pakietów i biblioteka standardowa

Kiedy aktualizujesz pakiet w Dark, nie zastępujemy natychmiast użycia każdej funkcji lub typu w całej bazie kodu. To nie jest bezpieczne. Kod nadal korzysta z tej samej wersji, z której korzystał, a użycie funkcji i typów aktualizuje się do nowej wersji w poszczególnych przypadkach za pomocą przełączników.

How Dark wdraża kod w 50 ms
Zrzut ekranu przedstawiający część automatycznego procesu w Dark, przedstawiający dwie wersje funkcji Dict::get. Dict::get_v0 zwrócił typ Any (który odrzucamy), a Dict::get_v1 zwrócił typ Option.

Często udostępniamy nową funkcję biblioteki standardowej i wykluczamy starsze wersje. Użytkownicy posiadający starsze wersje kodu nadal będą mieli do nich dostęp, ale nowi użytkownicy nie będą mogli uzyskać do nich dostępu. Zamierzamy zapewnić narzędzia umożliwiające migrację użytkowników ze starych wersji do nowych w jednym kroku, ponownie przy użyciu przełączników funkcji.

Dark zapewnia również unikalną funkcję: ponieważ uruchamiamy Twój kod produkcyjny, możemy sami testować nowe wersje, porównując wyniki nowych i starych zapytań, aby poinformować Cię o zmianach. W rezultacie aktualizacje pakietów, które często są przeprowadzane na ślepo (lub wymagają szeroko zakrojonych testów bezpieczeństwa), stwarzają znacznie mniejsze ryzyko i mogą odbywać się automatycznie.

Nowe wersje Darka

Przejście z Pythona 2 na Pythona 3 trwało dekadę i nadal stanowi wyzwanie. Ponieważ tworzymy Dark z myślą o ciągłym dostarczaniu, musimy wziąć pod uwagę te zmiany językowe.

Kiedy wprowadzamy drobne zmiany w języku, tworzymy nową wersję Dark. Stary kod pozostaje w starej wersji Dark, a nowy kod jest używany w nowej wersji. Możesz użyć przełączników lub wersji funkcji, aby uaktualnić Dark do nowej wersji.

Jest to szczególnie przydatne, biorąc pod uwagę, że tryb Dark został wprowadzony dopiero niedawno. Wiele zmian w języku lub bibliotece może zakończyć się niepowodzeniem. Przyrostowe wersjonowanie języków pozwala nam na wprowadzanie drobnych aktualizacji, co oznacza, że ​​możemy nie spieszyć się i odłożyć wiele decyzji dotyczących języka do czasu, aż będziemy mieli więcej użytkowników, a tym samym więcej informacji.

Migracje baz danych

Istnieje możliwość bezpiecznej migracji baz danych standardowa formuła:

  • Przepisz kod, aby obsługiwał nowe i stare formaty
  • Konwertuj wszystkie dane na nowy format
  • Usuń stary dostęp do danych

W rezultacie migracja bazy danych zajmuje dużo czasu i wymaga dużych zasobów. W rezultacie gromadzi się przestarzałe schematy, ponieważ nawet proste zadania, takie jak poprawianie nazwy tabeli lub kolumny, nie są warte wysiłku.

Dark ma wydajną platformę do migracji baz danych, która (mamy nadzieję) sprawi, że proces będzie tak łatwy, że nie będziesz się go obawiać. Wszystkie magazyny danych w Dark (magazyny klucz-wartość lub trwałe tabele skrótów) mają typ. Aby przeprowadzić migrację magazynu danych, po prostu przypisz mu nowy typ oraz użyj funkcji cofania i przewijania do przodu, aby przekonwertować wartości między tymi dwoma typami.

Dostęp do magazynów danych w Dark jest możliwy poprzez wersjonowane nazwy zmiennych. Na przykład magazyn danych Users będzie początkowo nosił nazwę Users-v0. Kiedy tworzona jest nowa wersja innego typu, nazwa zmienia się na Users-v1. Jeżeli dane są zapisywane poprzez Users-v0 i uzyskujesz do nich dostęp poprzez Users-v1, stosowana jest funkcja odtwarzania zmian. Jeżeli dane są zapisywane w wersji Users-v1 i uzyskujesz do nich dostęp poprzez Users-v0, stosowana jest funkcja przywracania zmian.

How Dark wdraża kod w 50 ms
Ekran migracji bazy danych przedstawiający stare nazwy pól bazy danych, wyrażenia dotyczące przewijania i wycofywania oraz instrukcje dotyczące włączania migracji.

Użyj przełączników funkcji, aby przekierować wywołania do Users-v0 do Users-v1. Można to zrobić pojedynczo, aby zmniejszyć ryzyko, a przełączniki działają dla poszczególnych użytkowników, dzięki czemu można sprawdzić, czy wszystko działa zgodnie z oczekiwaniami. Gdy nie ma już użytkowników Users-v0, Dark przekonwertuje wszystkie pozostałe dane w tle ze starego formatu na nowy. Nawet tego nie zauważysz.

Testowanie

Ciemno jest funkcjonalny język programowania z typowaniem statycznym i niezmienne wartości, więc jego powierzchnia testowa jest znacznie mniejsza w porównaniu z dynamicznie typowanymi językami obiektowymi. Ale nadal musisz przetestować.
W Dark edytor automatycznie uruchamia w tle testy jednostkowe dla edytowanego kodu i domyślnie uruchamia te testy dla wszystkich przełączników funkcji. W przyszłości chcemy używać typów statycznych do automatycznego fuzowania kodu w celu znalezienia błędów.

Dodatkowo Dark uruchamia Twoją infrastrukturę w środowisku produkcyjnym, co otwiera nowe możliwości. Automatycznie zapisujemy żądania HTTP w środowisku Dark (na razie zapisujemy wszystkie żądania, ale potem chcemy przejść do pobierania). Testujemy pod nimi nowy kod i przeprowadzamy testy jednostkowe, a jeśli chcesz, w łatwy sposób możesz zamienić ciekawe zapytania na testy jednostkowe.

Czego się pozbyliśmy?

Ponieważ nie mamy wdrożenia, ale mamy przełączniki funkcji, około 60% procesu wdrażania pozostaje w tyle. Nie potrzebujemy gałęzi git ani żądań ściągnięcia, budowania zasobów i kontenerów zaplecza, wypychania zasobów i kontenerów do rejestrów ani etapów wdrażania w Kubernetes.

How Dark wdraża kod w 50 ms
Porównanie standardowego rurociągu ciągłego dostarczania (po lewej) i ciemnego rurociągu ciągłego dostarczania (po prawej). Dostawa Dark składa się z 6 kroków i jednego cyklu, natomiast tradycyjna wersja obejmuje 35 kroków i 3 cykle.

W Dark wdrożenie składa się tylko z 6 kroków i 1 cyklu (kroki powtarzane kilka razy), podczas gdy nowoczesny potok ciągłego dostarczania składa się z 35 kroków i 3 cykli. W trybie Dark testy uruchamiają się automatycznie, a Ty nawet tego nie widzisz; zależności są instalowane automatycznie; wszystko, co jest związane z gitem lub Githubem, nie jest już potrzebne; Nie ma potrzeby budowania, testowania i wysyłania kontenerów Docker; wdrożenie do Kubernetes nie jest już konieczne.

Nawet pozostałe kroki w Dark stały się łatwiejsze. Ponieważ przełączaniem funkcji można sterować za pomocą jednej akcji, nie ma potrzeby ponownego wykonywania całego procesu wdrażania w celu usunięcia starego kodu.

Uprościliśmy dostarczanie kodu najlepiej jak potrafiliśmy, redukując czas i ryzyko ciągłego dostarczania. Znacznie ułatwiliśmy także aktualizację pakietów, migrację baz danych, testowanie, kontrolę wersji, instalację zależności, równość środowisk programistycznych i produkcyjnych oraz szybkie i bezpieczne aktualizacje wersji językowych.

Odpowiadam na pytania w tej sprawie HackerNews.

Aby dowiedzieć się więcej o urządzeniu Dark, przeczytaj artykuł o Darku, Śledź nas na Twitterze (lub o godz ja) lub zarejestruj się w wersji beta i otrzymuj powiadomienia o nadchodzących wpisach. Jeśli wybierasz się do StrangeLoop we wrześniu, przyjdź na naszą premierę.

Źródło: www.habr.com

Dodaj komentarz