Dla mojego męża, Glena
W dniu, w którym się spotkaliśmy, zmieniło się całe moje życie

Dla mojego syna, Maksa
W dniu, w którym się urodziłeś, zmieniło się całe moje życie

Dane oryginału

Original edition copyright © 2019 by Manning Publications Co. All rights reserved. Title of English-language original: Cloud Native Patterns by Cornelia Davis, ISBN 978-1-61729-429-7. Polish-language edition © 2020 by Polish Scientific Publishers PWN Wydawnictwo Naukowe PWN Spółka Akcyjna. All Rights reserved.

Przekład Wojciech Urbański

Projekt okładki polskiego wydania Joanna Andryjowicz

Wydawca Wioleta Szczygielska-Dybciak

Redaktor prowadzący Jolanta Kowalczuk

Redaktor Dorota Polewicz

Skład wersji elektronicznej na zlecenie Wydawnictwa Naukowego PWN: Marcin Kośka, Woblink

Koordynator produkcji Anna Bączkowska

Zastrzeżonych nazw firm i produktów użyto w książce wyłącznie w celu identyfikacji.

Książka, którą nabyłeś, jest dziełem twórcy i wydawcy. Prosimy, abyś przestrzegał praw, jakie im przysługują. Jej zawartość możesz udostępnić nieodpłatnie osobom bliskim lub osobiście znanym. Ale nie publikuj jej w internecie. Jeśli cytujesz jej fragmenty, nie zmieniaj ich treści i koniecznie zaznacz, czyje to dzieło. A kopiując jej część, rób to jedynie na użytek osobisty.

Szanujmy cudzą własność i prawo

Więcej na www.legalnakultura.pl

Polska Izba Książki

Copyright © for the Polish edition by Wydawnictwo Naukowe PWN SA

Warszawa 2020

ISBN 978-83-01-21349-7

eBook został przygotowany na podstawie wydania papierowego z 2020 r., (wyd. I) Warszawa 2020

Wydawnictwo Naukowe PWN SA

02-460 Warszawa, ul. Gottlieba Daimlera 2

tel. 22 69 54 321, faks 22 69 54 288

infolinia 801 33 33 88

e-mail: pwn@pwn.com.pl, reklama@pwn.pl

www.pwn.pl

Spis treści

przedmowa

wstęp

podziękowania

o książce

o autorce

o ilustracji na okładce

Część 1 Kontekst cloud-native

1 Wciąż używasz tego słowa: definiując „cloud-native”

1.1. Wymagania dzisiejszych aplikacji

Brak przestojów

Skrócone cykle informacji zwrotnej

Wsparcie urządzeń mobilnych i wielu urządzeń

Połączone urządzenia – tak zwany internet rzeczy

Kierowane danymi (data-driven)

1.2. Wprowadzenie oprogramowania cloud-native

Definiując cloud-native

Model myślowy dla oprogramowania cloud-native

Oprogramowanie cloud-native w akcji

1.3. Cloud-native a pokój na świecie

Chmura (cloud) a cloud-native

Czym nie jest cloud-native

Cloud-native jest miłe

2 Uruchamianie aplikacji cloud-native na produkcji

2.1. Przeszkody

Płatki śniegu

Ryzykowne wdrożenia

Zmiana jest wyjątkiem

Niestabilność na produkcji

2.2. Aktywatory

Ciągłe dostarczanie

Powtarzalność

Bezpieczne wdrożenia

Zmiana jest regułą

3 Platforma dla oprogramowania cloud-native

3.1. Ewolucja platform cloud(-native)

Zaczęło się od chmury

Sygnał wybierania cloud-native

3.2. Podstawowe zasady platformy cloud-native

Po pierwsze, porozmawiajmy o kontenerach

Wsparcie dla „ciągle zmieniających się”

Wsparcie dla „wysoko rozproszonych”

3.3. Kto co robi?

3.4. Więcej możliwości platform cloud-native

Platforma wspiera cały cykl życia oprogramowania

Bezpieczeństwo, kontrola zmian, compliance (funkcje kontrolne)

Kontrola tego, co wchodzi do kontenera

Aktualizacje i łatanie podatności

Kontrola zmian

Część 2 Wzorce cloud-native

4 Zdarzeniowe mikroserwisy: nie tylko żądanie-odpowiedź

4.1. Jesteśmy (zwykle) uczeni programowania imperatywnego

4.2. Wracamy do przetwarzania zdarzeniowego

4.3. Moja globalna książka kucharska

Żądanie-odpowiedź

Architektura zdarzeniowa

4.4. Wprowadzenie CQRS – Command Query Responsibility Segregation

4.5. Inne style, podobne wyzwania

5 Redundancja aplikacji: skalowanie poziome i bezstanowość

5.1. Aplikacje cloud-native mają wiele uruchomionych instancji

5.2. Stanowe aplikacje w chmurze

Dekompozycja monolitu i powiązanie z bazą danych

Słaba obsługa stanu sesji

5.3. Sesje HTTP i lepkie sesje

5.4. Stanowe usługi i bezstanowe aplikacje

Stanowe usługi to usługi wyjątkowe

Zmiana aplikacji na bezstanową

6 Konfiguracja aplikacji: nie tylko zmienne środowiskowe

6.1. Dlaczego w ogóle rozmawiamy o konfiguracji?

Dynamiczne skalowanie – zwiększanie i zmniejszanie liczby instancji aplikacji

Zmiany infrastruktury powodujące zmiany konfiguracji

Aktualizacja konfiguracji aplikacji bez przestoju

6.2. Warstwa konfiguracji aplikacji

6.3. Wstrzykiwanie wartości systemowych/środowiskowych

Zobaczmy to w akcji: używanie zmiennych środowiskowych dla konfiguracji

6.4. Wstrzykiwanie konfiguracji aplikacji

Wprowadzenie serwera konfiguracji

Bezpieczeństwo dostarcza kolejnych wymagań

Zobaczmy to w akcji: konfiguracja aplikacji z wykorzystaniem serwera konfiguracyjnego

7 Cykl życia aplikacji: uwzględnianie ciągłych zmian

7.1. Współczucie dla działu operatorów

7.2. Cykl życia jednej aplikacji, cykle życia wielu instancji

Aktualizacje blue/green

Stopniowa aktualizacja

Równoległe wdrożenia

7.3. Koordynacja różnych cyklów życia aplikacji

7.4. Zobaczmy to w akcji: wymiana poświadczeń a cykl życia aplikacji

7.5. Radzenie sobie z efemerycznymi środowiskami uruchomieniowymi

7.6. Widoczność stanu cyklu życia aplikacji

Zobaczmy to w akcji: węzły stanu zdrowia i sondy

7.7. Serverless

8 Dostęp do aplikacji: usługi, trasy i wyszukiwanie usług

8.1. Abstrakcja usługi

Przykład usługi: googlowanie

Przykład usługi: nasz agregator blogów

8.2. Dynamiczny routing

Równoważenie obciążenia po stronie serwera

Równoważenie obciążenia po stronie klienta

Aktualność tras

8.3. Wyszukiwanie usług

Wyszukiwanie usług w sieci

Wyszukiwanie usług z równoważeniem ruchu po stronie klienta

Wyszukiwanie usług w Kubernetesie

Zobaczmy to w akcji: wykorzystanie wyszukiwania usług

9 Redundancja interakcji: powtarzanie i inne pętle sterowania

9.1. Powtarzanie żądań

Podstawowe powtórzenie żądania

Zobaczmy to w akcji: proste powtórzenia

Powtórzenia: co może pójść nie tak?

Wywoływanie burzy powtórzeń

Zobaczmy to w akcji: wywoływanie burzy powtórzeń

Unikanie burz powtórzeń: uprzejmi klienci

Zobaczmy to w akcji: bycie bardziej uprzejmym klientem

Kiedy nie powtarzać

9.2. Logika awaryjna

Zobaczmy to w akcji: implementacja logiki awaryjnej

9.3. Pętle sterowania

Zrozumienie typów pętli sterowania

Sterowanie pętlą sterowania

10 Fasady usług: bezpieczniki (circuit breakers) i bramy API

10.1. Bezpieczniki

Bezpiecznik w oprogramowaniu

Implementacja bezpiecznika

10.2. Bramy API

Sprawa bramy API w oprogramowaniu cloud-native

Topologia bramy API

10.3. Service mesh

Sidecar

Płaszczyzna sterowania

11 Rozwiązywanie problemów: odnaleźć igłę w stogu siana

11.1. Logowanie aplikacji

11.2. Metryki aplikacji

Ściąganie metryk z aplikacji cloud-native

Wysyłanie metryk z aplikacji cloud-native

11.3. Rozproszone śledzenie

Ślady w wyjściu usług

Składanie śladów za pomocą Zipkina

Szczegóły implementacji

12 Dane cloud-native: przełamywanie monolitu danych

12.1. Każdy mikroserwis potrzebuje pamięci podręcznej

12.2. Przejście od żądań i odpowiedzi do zdarzeniowości

12.3. Dziennik zdarzeń

Zobaczmy to w akcji: implementacja zdarzeniowych mikroserwisów

Co nowego w tematach i kolejkach?

Zawartość zdarzenia

Idempotentność

12.4. Event sourcing

Dotychczasowa podróż

Źródło prawdy

Zobaczmy to w akcji: implementacja event sourcingu

12.5. Ledwo zadrapaliśmy powierzchnię

Przypisy

przedmowa

Przez sześć lat miałem przywilej pracy z Nicole Forsgren i Jezem Humble’em nad „State of DevOps Report” (Raport o stanie DevOps), który zebrał dane od ponad 30 000 respondentów. Jednym z największych dla mnie objawień była istotność architektury oprogramowania: wysokowydajne zespoły działały w architekturach, które pozwalały programistom na szybkie i niezależne rozwijanie, testowanie i dostarczanie wartości do klientów, bezpiecznie i niezawodnie.

Dekady temu mogliśmy żartować, że architekci oprogramowania byli ekspertami jedynie w używaniu Visio, tworzeniu diagramów UML i generowaniu slajdów w PowerPoincie, na które nikt nigdy nie patrzył. Jeśli nawet było to prawdą, to teraz zdecydowanie tak nie jest. W dzisiejszych czasach biznesy wygrywają i przegrywają na rynku dzięki oprogramowaniu, które tworzą. A nic nie wpływa na codzienną pracę programistów bardziej niż infrastruktura, w której muszą pracować.

Ta książka wypełnia pustkę rozpiętą między teorią a praktyką. Tak naprawdę myślę, że tylko garstka ludzi mogła ją napisać. Cornelia Davis jest wyjątkowo wykwalifikowana, po spędzeniu lat na doktoracie, ucząc się o językach programowania, rozwinąwszy miłość do programowania funkcyjnego i niezmienności, pracując przez dekady z dużymi systemami oprogramowania i pomagając osiągnąć wielkość dużym organizacjom pracującym nad oprogramowaniem.

Przez ostatnich pięć lat wielokrotnie zwracałem się do niej o pomoc i porady, często w takich tematach jak CQRS i event sourcing, LISP i Clojure (mój ulubiony język programowania), niebezpieczeństwa programowania imperatywnego i stanu, a nawet w takich prostych rzeczach jak rekurencja.

Tym, co sprawia, że czytanie tej książki daje taką satysfakcję, jest fakt, że Cornelia nie zaczyna po prostu od wzorców. Zaczyna od pierwszych zasad, a następnie udowadnia ich ważność przez argumentację, czasami logiczną, a czasami przy użyciu schematów blokowych. Niezadowalając się teorią, implementuje następnie te wzorce za pomocą Java Spring, iteracja po iteracji, uwzględniając to, czego się nauczyłeś.

Uważam, że ta książka bawi i uczy, a ja poznałem niewiarygodną ilość tematów, o których kiedyś miałem tylko pobieżne pojęcie. Postanowiłem teraz zaimplementować jej przykłady w Clojure, ponieważ chcę udowodnić, że potrafię przekuć tę wiedzę w praktykę.

Spodziewam się, że znajdziesz tu koncepcje, które cię zachwycą, a może nawet nieco zaskoczą. Dla mnie jednym z tych konceptów była potrzeba centralizacji przekrojowych problemów za pomocą programowania zorientowanego aspektowo, sidecarów w Kubernetesie czy wstrzykiwania Spring Retry.

Mam nadzieję, że uznasz tę książkę za tak wartościową, jak ja ją za taką uznałem!

Gene Kim

badacz i współautor The Phoenix Project,

The Devops Handbook i Accelerate

wstęp

Zaczęłam moją karierę od przetwarzania obrazów. Pracowałam w Dziale Systemów Rakietowych w Hughes Aircraft nad obrazami w podczerwieni, robiąc takie rzeczy jak wykrywanie krawędzi i korelacja klatka-do-klatki (niektóre z tych rzeczy znajdziesz w wielu aplikacjach na swojej komórce – to wszystko działo się w latach osiemdziesiątych!).

Jednym z obliczeń, które wykonujemy często w przetwarzaniu obrazów, jest odchylenie standardowe. Nigdy nie byłam specjalnie wstydliwa w kwestii zadawania pytań, a jedno, które zadawałam bardzo wcześnie w tych swoich początkowych dniach pracy, było związane z odchyleniem standardowym. Niezmiennie kolega zapisywał następujące równanie:

Ale przecież znałam wzór na odchylenie standardowe – po trzech miesiącach pracy zaprogramowałam je pewnie z pół tuzina razy. Tak naprawdę pytałam: „Co znajomość odchylenia standardowego mówi nam w tym kontekście?” Odchylenie standardowe wykorzystuje się do definiowania, co jest „normalne”, byśmy mogli spojrzeć na odstające wartości. Jeśli liczę odchylenie standardowe, a następnie znajduję rzeczy poza normą, to czy jest to znak, że mój czujnik mógł nie działać poprawnie i muszę wyrzucić ramkę obrazu, czy może ujawnia to potencjalne akcje wroga?

Co to ma wspólnego z cloud-native? Nic. Za to wszystko z wzorcami. Widzisz, ja znałam wzorzec – równanie odchylenia standardowego – ale z powodu mojego braku doświadczenia w tamtym czasie miałam problem z tym, kiedy i jak je stosować.

W tej książce nauczę cię wzorców dla aplikacji cloud-native i tak, pokażę ci wiele „równań”, ale spędzę dużo więcej czasu nad kontekstem – tym, kiedy i dlaczego aplikować te wzorce. Tak naprawdę wzorce ogólnie nie są tak trudne (np. powtarzanie żądań, opisywane w rozdziale 9, jest prostym konceptem, łatwym do implementacji). Ale wybór tego, kiedy zastosować wzorzec i jak dokładnie to zrobić – to już bywa podchwytliwe. Jest tak wiele rzeczy do zrozumienia o kontekście, w którym będziesz aplikować te wzorce, i, szczerze mówiąc, ten kompleks może być złożony.

Czym jest zatem ten kontekst? Zasadniczo to kontekst systemów rozproszonych. Kiedy rozpoczęłam moją karierę ponad trzydzieści lat temu, nie znałam wielu osób, które pracowały nad systemami rozproszonymi, i nie wybrałam na studiach przedmiotu o systemach rozproszonych. Tak, ludzie pracowali w tym obszarze, ale, prawdę mówiąc, był on dosyć niszowy.

Dzisiaj większość oprogramowania jest systemem rozproszonym. Niektóre części twojego oprogramowania działają w przeglądarce, a inne na serwerze lub, pozwolę sobie powiedzieć, całym mnóstwie serwerów. Te serwery mogą działać w twojej firmowej serwerowni albo w ciemnym centrum danych w Prineville w Oregonie, albo w obu miejscach. Ostatecznie wszystkie te części komunikują się po sieci, prawdopodobnie internetowej, a jest duża szansa, że twoje dane także są rozproszone. Mówiąc prosto, oprogramowanie cloud-native jest systemem rozproszonym. Dodatkowo rzeczy są w nieustannym stanie zmiany – serwery, na których pracujesz, są przenoszone, sieci mają częste awarie, nawet jeśli krótkie, a pamięci dyskowe mogą się wywrócić do góry brzuchem bez ostrzeżenia – mimo to od twojego oprogramowania oczekuje się poprawnego działania. To dosyć trudna sytuacja.

Lecz jest całkowicie możliwa do kontroli! Moim zadaniem w tej książce jest pomóc ci zrozumieć ten kontekst i dostarczyć narzędzi, abyś mógł zostać skutecznym architektem i programistą oprogramowania cloud-native.

Nigdy jeszcze nie byłam tak intelektualnie pobudzona jak teraz. To w dużej mierze dlatego, że krajobraz technologiczny zmienia się w znaczący sposób, a cloud-native jest w samym środku tego procesu. Absolutnie kocham to, czym zarabiam na życie, i nie chcę niczego więcej ponad to, by każdy, szczególnie ty, czerpał przyjemność z pisania oprogramowania tak jak ja. I dlatego napisałam tę książkę: chcę podzielić się z tobą fantastycznymi problemami, nad którymi pracujemy jako branża, i pomóc ci w drodze do umiejętności ich rozwiązywania. Jestem zaszczycona, że mam możliwość odegrania nawet małej roli w twoim locie do chmury.

podziękowania

Moja podróż cloud-native rozpoczęła się naprawdę w 2012 roku, gdy mój ówczesny szef, Tom Maguire, poprosił mnie, żebym rozeznała się w  temacie tego całego PaaS (Platform as a Service). Jako członkowi grupy Architektury w biurze CTO EMC zwracanie uwagi na powstające technologie nie było dla nas niczym nowym – ale to się wspaniale poukładało! Będę wiecznie wdzięczna Tomowi za rozpęd i oddanie mi miejsca na eksplorację.

Na początku roku 2013 nauczyłam się wystarczająco dużo, by wiedzieć, że to była przestrzeń do pracy dla mnie na najbliższą przyszłość, a po stworzeniu Pivotal Software miałam miejsce do wykonywania tej pracy. Muszę podziękować Elisabeth Hendrickson po pierwsze za powitanie mnie w ekipie Cloud Foundry – nawet gdy jeszcze pracowałam w EMC – i po drugie za przedstawienie mnie Jamesowi Wattersowi. Często mówię, że najlepszym krokiem, jaki kiedykolwiek zrobiłam w mojej karierze, było przejście do pracy dla Jamesa. Jestem mu wdzięczna za wiele możliwości, które mi przedstawił, za zaufanie do mnie, które pozwoliło mi na wykonywanie mojej najlepszej pracy, za niezliczone, obszerne rozmowy, w których wspólnie poznawaliśmy to całe cloud-native, oraz za głęboką przyjaźń, którą stworzyliśmy przez ostatnie sześć lat.

Jestem wdzięczna, że byłam częścią firmy Pivotal od jej powstania, gdzie uczyłam się w towarzystwie tak wielu światłych, oddanych i uprzejmych kolegów. Chciałabym podziękować Elisabeth Hendrickson, Joshua McKenty’emu, Andrew Clay-Shaferowi, Scottowi Yarowi, Ferranowi Rodenasowi, Mattowi Stine’owi, Ragvenderowi Arniemu i wielu innym (proszę, wybaczcie, jeśli kogoś pominęłam) za pomoc w nauce i za współdzielenie sześciu najlepszych lat mojego życia! Chciałabym także podziękować firmie Pivotal, w szczególności Ianowi Andrewsowi i Kelly Hall, za sponsorowanie miniksiążki Cloud-Native Foundations (Podstawy cloud-native).

Nauczyłam się tak wiele od wielu więcej kolegów z branży, niż jestem w stanie wymienić – dziękuję każdemu z was. Ale chciałabym wyróżnić Gene’a Kima. Pamiętam wieczór, gdy się poznaliśmy (i ponownie dziękuję Elisabeth Hendrickson za rolę, którą odegrała w umożliwieniu tego spotkania), i od razu wiedziałam, że będziemy współpracować przez długi czas. Dziękuję Gene’owi za możliwość pracy z nim nad konferencją DevOps Enterprise Summit, dzięki której poznałam bardzo wielu innowacyjnych ludzi, pracujących w szerokiej gamie firm. Dziękuję mu za jedne z najbardziej ożywczych, poszerzających horyzonty rozmów. I dziękuję mu za napisanie przedmowy do tej książki.

Oczywiście dziękuję Wydawnictwu Manning za możliwość napisania tej książki, rozpoczynając od Mike’a Stephensa, który pomógł mi przejść od bezczynnej ciekawości o pisaniu książki do faktycznego skoku na głęboką wodę. Mam dług wdzięczności wobec mojej edytorki Christiny Taylor. Wzięła pod opiekę początkującą autorkę, która zaczęła z 20-rozdziałowym bałaganem pomysłów i pierwszą wersją rozdziału, który ciągnął się przez jakieś 70 stron, oraz pomogła mi stworzyć książkę, która ma strukturę i prawdziwą fabułę. Była przy mnie przez ponad dwa i pół roku, zachęcając mnie, gdy byłam na dnie rozpaczy, i świętując ze mną, gdy byłam na szczycie osiągnięć. Dziękuję także zespołowi produkcji, w tym Sharon Wilkey, Deirdre Hiam, Neilowi Crollowi, Carol Shields i Nichole Beard, którzy są odpowiedzialni za doprowadzenie tego wszystkiego do mety. I dziękuję moim recenzentom – Bachirowi Chihaniemu, Carlosowi Robertowi Vargasowi Monterowi, Davidowi Schmitzowi, Doniyorowi Ulmasovi, Gregorowi Zurowskiemu, Jaredowi Duncanowi, Johnowi Guthriemu, Jorge’owi Ezequielowi Bo, Kelvinowi Johnsonowi, Kentowi R. Spillnerowi, Lonnie Smetanie, Luisowi Carlosowi Sanchezowi Gonzalezowi, Markowi Millerowi, Peterowi Paulowi Sellarsowi, Raveeshowi Sharmie, Sergeyowi Evsikovowi, Sergiowi Martinezowi, Shankerowi Janakiramanowi, Stefanowi Hellwegerowi, Winowi Oo oraz Zorodzayi Mukuya. Wasze uwagi miały znaczący wpływ na ukończony produkt.

I przede wszystkim dziękuję mojemu mężowi Glenowi i synowi Maksowi za ich cierpliwość, zachęty i niezawodną wiarę we mnie. Oni, bardziej niż ktokolwiek inny, są dwiema osobami, które to umożliwiły, nie tylko wspierając mnie przez ostatnie niemal trzy lata, ale także przez pomaganie mi w układaniu fundamentów przez kilka wcześniejszych dekad. Dla was dwóch mam najserdeczniejszą wdzięczność. A to, że ty, Maksie, zakochałeś się w komputerach tak jak ja i pozwoliłeś mi być obserwatorem tej podróży, jest podwójną polewą czekoladową na torcie death-by-chocolate – dziękuję!

o książce

Kto powinien przeczytać tę książkę

Przejście „do chmury” to bardziej zmiana tego, jak projektujesz swoje aplikacje, niż tego, gdzie je uruchamiasz. Wzorce cloud-native: projektowanie oprogramowania odpornego na zmiany to twój przewodnik do tworzenia mocnych aplikacji, które radzą sobie w dynamicznym, rozproszonym, wirtualnym świecie chmury. Ta książka prezentuje myślowy model aplikacji cloud-native wraz ze wzorcami, praktykami i narzędziami wspierającymi ich tworzenie. Znajdziesz w niej realistyczne przykłady i eksperckie porady dotyczące pracy z aplikacjami, danymi, usługami, routingiem i innymi elementami.

Zasadniczo jest to książka o architekturze, zawierająca przykłady kodu wspierające zawarte w niej dyskusje związane z designem aplikacji. Zauważysz, że często odnoszę się do różnic między wzorcami, które omawiam tutaj, i do sposobu, w który mogłeś robić pewne rzeczy w przeszłości. Posiadanie doświadczenia z wzorcami poprzedniej ery czy nawet ich znajomość nie są jednak wymagane. Ponieważ omawiam nie tylko same wzorce, ale także motywacje do ich użycia i niuanse kontekstu, w którym są stosowane, powinieneś odnieść sporą korzyść niezależnie od tego, ile lat spędziłeś w pracy z oprogramowaniem.

I mimo że w książce pojawia się wiele przykładów kodu, to nie jest książka programistyczna. Nie nauczy cię, jak programować, jeśli nie znasz jeszcze podstaw. Przykłady kodu są w Javie, ale doświadczenie z dowolnym językiem programowania powinno pozwolić ci nadążać bez problemu. Posiadanie podstawowego zrozumienia interakcji między klientem a usługą, w szczególności przy użyciu protokołu HTTP, jest także pomocne, ale nie jest konieczne.

Jak książka jest zorganizowana: mapa

Książka ma 12 rozdziałów podzielonych na dwie części.

Część 1 definiuje kontekst cloud-native i prezentuje charakterystyki środowiska, w którym będziesz uruchamiać oprogramowanie:

- Rozdział 1 definiuje cloud-native i różnice względem samej chmury. Prezentuje model myślowy, wokół którego można zbudować wzorce, które pojawią się później: obiektami tego modelu są aplikacje/usługi, interakcje między usługami oraz dane.

- Rozdział 2 omawia operacje w środowisku cloud-native: wzorce i praktyki wykorzystywane do utrzymania oprogramowania cloud-native w działaniu na produkcji mimo wszystkich nieuniknionych przeszkód, które zostaną na nie narzucone.

- Rozdział 3 wprowadza platformę cloud-native, środowisko programowania i uruchamiania aplikacji, które dostarcza wsparcia, a nawet implementacji wielu wzorców zaprezentowanych w drugiej części książki. Chociaż ważne jest, byś zrozumiał wszystkie wzorce, które się pojawią, nie musisz ich wszystkich implementować.

Część 2 to dogłębna analiza samych wzorców cloud-native:

- Rozdział 4 dotyczy interakcji cloud-native, dotyka także nieco danych, wprowadzając zdarzeniową komunikację jako alternatywę dla znajomego stylu żądanie/ odpowiedź. Mimo że ten drugi jest niemal wszechobecny w większości dzisiejszego oprogramowania, podejścia zdarzeniowe często oferują znaczące korzyści w wysoko rozproszonym oprogramowaniu cloud-native i ważne jest rozważenie obu protokołów, poznając nadchodzące wzorce.

- Rozdział 5 mówi o aplikacjach/usługach cloud-native i ich relacjach z danymi. Wyjaśnia, jak aplikacje są uruchamiane jako redundantne instancje, często w znaczących ilościach, jak i dlaczego sprawiać, by były bezstanowe, i jak powiązać je ze specjalną stanową usługą.

- Rozdział 6 traktuje o aplikacjach/usługach cloud-native. Mówi o tym, jak konfiguracja aplikacji może być spójnie utrzymywana, gdy wiele, wiele instancji jest uruchamianych na przestrzeni szeroko rozproszonej infrastruktury. Omawia także to, jak konfiguracje aplikacji można poprawnie aplikować, gdy środowisko ich działania nieustannie się zmienia.

- Rozdział 7 dotyczy również aplikacji/usług cloud-native. Objaśnia cykl życia aplikacji i liczne praktyki aktualizacji bez przestojów, w tym aktualizacje stopniowe i blue/green.

- Rozdział 8 mówi o interakcjach cloud-native. Skupia się zarówno na tym, jak aplikacje mogą odnaleźć usługi, których potrzebują (wyszukiwanie usług), nawet jeśli te usługi nieustannie się przenoszą, jak i na tym, jak żądania ostatecznie trafiają do odpowiednich usług (dynamiczny routing).

- Rozdział 9 dotyczy interakcji cloud-native. Koncentruje się na klienckiej stronie interakcji. Po wyjaśnieniu konieczności redundancji interakcji i zaprezentowaniu powtórzeń (w których żądania są powtarzane, jeśli początkowo się nie powiodą), rozdział omawia zarówno problemy, które mogą wyniknąć z naiwnego zastosowania powtórzeń, jak i sposoby, by ich uniknąć.

- Rozdział 10 omawia interakcje cloud-native. Skupia się na stronie usługi. Nawet jeśli klienci inicjujący interakcje robią to odpowiedzialnie, usługa musi się nadal chronić przed nadużyciami i przeładowaniem ruchem. Ten rozdział omawia bramy PAI i bezpieczniki.

- Rozdział 11 mówi zarówno o aplikacjach, jak i interakcjach. Prezentuje sposoby na obserwowanie zachowań i wydajności rozproszonego systemu, tworzącego twoje oprogramowanie.

- Rozdział 12 dotyczy danych i zawiera znaczące implikacje dla interakcji między usługami tworzącymi twoje oprogramowanie cloud-native. Omawia wzorce wykorzystywane do zmiany tego, co kiedyś było monolityczną bazą danych, w rozproszoną sieć danych, ostatecznie powracając do zdarzeniowych wzorców, omawianych na początku drugiej części książki.

O kodzie

Książka zawiera wiele przykładów kodu źródłowego, zarówno w ponumerowanych listingach, jak i w normalnej treści książki. W obu sytuacjach kod źródłowy jest formatowany czcionką o stałej szerokości, jak ta, by oddzielić go od zwykłego tekstu. Czasami kod jest także pogrubiony, żeby zaznaczyć części, które powinny zwrócić twoją uwagę.

W wielu sytuacjach oryginalny kod źródłowy został ponownie sformatowany; dodaliśmy złamania linii i przerobiliśmy wcięcia, by uwzględnić dostępne miejsce na stronie w książce. W rzadkich sytuacjach nawet to nie wystarczyło i listingi zawierają znaczniki kontynuacji linii (). Oprócz tego komentarze z kodu źródłowego zostały usunięte z listingów, jeśli kod jest omawiany w tekście. Adnotacje przy kodzie towarzyszą wielu listingom, oznaczając ważne zagadnienia.

Kod przykładów z książki jest dostępny do pobrania ze strony Manning pod adresem https://www.manning.com/books/cloud-native-patterns oraz z GitHuba https://github.com/cdavisafc/cloudnative-abundantsunshine.

Forum dyskusyjne liveBook

Zakup Wzorców cloud-native zawiera darmowy dostęp do prywatnego forum internetowego wydawnictwa Manning Publications, gdzie możesz komentować książkę, zadawać techniczne pytania i otrzymywać pomoc od autora i innych użytkowników. Aby uzyskać dostęp do forum, przejdź pod adres https://livebook.manning.com/#!/book/cloud-native-patterns. Możesz także dowiedzieć się więcej o forach wydawnictwa Manning i zasadach postępowania pod adresem https://livebook.manning.com/#!/discussion.

Zaangażowanie ze strony wydawnictwa w pomoc dla naszych czytelników polega na zapewnieniu miejsca, gdzie może się odbywać istotny dialog między każdym z czytelników i autorką. Nie jest to zapewnienie jakiegokolwiek poziomu udziału ze strony autorki, której kontrybucje na forum pozostają dobrowolne (i bezpłatne). Sugerujemy spróbować zadać autorce kilka trudnych pytań, żeby jej zainteresowanie nie osłabło! Forum i archiwa poprzednich dyskusji będą dostępne na stronie wydawcy tak długo, jak książka pozostanie w druku.

Inne zasoby online

Możesz znaleźć Cornelię w sieci przez Twittera (@cdavisafc), Medium (https://medium.com/@cdavisafc) lub jej bloga http://corneliadavis.com.

o autorce

Cornelia Davis jest wiceprezeską do spraw technologii w firmie Pivotal, gdzie odpowiada za strategię technologiczną zarówno firmy, jak i jej klientów. Obecnie pracuje nad sposobami sprowadzenia zróżnicowanych modeli przetwarzania w chmurze, to jest Infrastructure as a Service, Applications as a Service, Container as a Service i Function as a Service, do jednego, spójnego produktu, który pozwoli firmom IT na funkcjonowanie na najwyższym poziomie.

Weteran branży z niemal trzema dekadami doświadczenia w przetwarzaniu obrazów, naukowych wizualizacjach, architekturach systemów rozproszonych i aplikacji webowych, a także platformach cloud-native, Cornelia uzyskała tytuły inżyniera i magistra inżyniera informatyki na California State University w Northridge, po czym studiowała teorię komputerów i języków programowania na Indiana University.

Jako nauczyciel z powołania Cornelia spędziła ostatnie trzydzieści lat, tworząc lepsze oprogramowanie i szkoląc lepszych programistów.

Kiedy nie robi żadnej z tych rzeczy, możesz ją znaleźć na macie do jogi lub w kuchni.

o ilustracji na okładce

Rysunek na okładce Wzorców cloud-native jest podpisany jako Habit of a Russian Midwife in 1764 (Ubiór rosyjskiej położnej z 1764 r.). Ilustracja pochodzi z dzieła A Collection of the Dresses of Different Nations, Ancient and Modern (4 tomy) Thomasa Jefferysa, opublikowanego w latach 1757–1772 w Londynie. Strona tytułowa oznajmia, że są to ręcznie kolorowane ryciny miedziorytów, wzmocnione gumą arabską.

Thomasa Jefferysa (1719–1771) nazywano „geografem króla Jerzego III”. Był angielskim kartografem, który w swoich czasach stał się czołowym dostawcą map. Grawerował i drukował mapy dla królewskich urzędów i innych oficjalnych organów oraz wytwarzał szeroki wachlarz komercyjnych map i atlasów, szczególnie Ameryki Północnej. Praca jako twórcy map wzbudziła jego zainteresowanie lokalnymi zwyczajami ubioru w obszarach przez niego badanych i mapowanych – zostały one doskonale ukazane w tej kolekcji. Fascynacja odległymi krajami i podróże dla przyjemności były względnie nowymi zjawiskami w końcu XVIII wieku, a kolekcje takie jak ta były popularne, prezentując mieszkańców innych krajów zarówno turystom, jak i podróżnikom nieruszającym się z fotela.

Różnorodność rycin w dziele Jefferysa wyraźnie mówi o wyjątkowości i indywidualności narodów świata około 200 lat temu. Sposoby ubierania się zmieniały się do naszych czasów, ale różnorodność regionów i krajów, tak bogata niegdyś, już wygasła. Dzisiaj często trudno jest odróżnić od siebie mieszkańców jednego czy drugiego kontynentu. Być może, próbując spojrzeć na to optymistycznie, zamieniliśmy kulturalną i widoczną różnorodność na bardziej zróżnicowane życie osobiste – lub bardziej zróżnicowane i interesujące życie intelektualne i techniczne.

W czasach, gdy trudno jest odróżnić od siebie różne książki poświęcone komputerom, Manning celebruje pomysłowość i inicjatywę branży komputerowej za pomocą okładek książek bazujących na różnorodności życia regionalnego sprzed ponad dwóch wieków, przywróconej do życia dzięki rycinom Jefferysa.

Część 1
Kontekst cloud-native

Chociaż może to zabrzmieć jak frazes, pierwsza część książki naprawdę przygotowuje grunt do wszystkiego. Podejrzewam, że mogłam przeskoczyć wprost do wzorców, o których na pewno z zapałem chcesz czytać (wyszukiwanie usług, bezpieczniki i inne), ale chcę, abyś zrozumiał te wzorce na tak głębokim poziomie, że te pierwsze rozdziały są konieczne. Zrozumienie kontekstu, w którym będą działać twoje aplikacje, zarówno na poziomie infrastruktury, jak i bardziej ludzkich elementów, pozwoli ci na zastosowanie wzorców w najefektywniejszy sposób. Oczekiwania klientów względem cyfrowych usług (nieustanna ewolucja i brak przestojów) oraz sposób, w jaki ty i współpracownicy je dostarczacie (zespoły z realnymi możliwościami i brak systemów zgłoszeniowych), mają powiązania z wzorcami projektowymi, których możesz się nie spodziewać.

Jednym z głównych zadań, które podejmuję w pierwszym rozdziale, jest definicja cloud-native, odróżniająca to od chmury (uwaga, spoiler: ta druga mówi o tym, gdzie, a to pierwsze o tym, jak, i to jest ta naprawdę interesująca część). Ustanawiam także myślowy model, wokół którego jest zorganizowana druga część książki.

Drugi rozdział mówi o utrzymywaniu aplikacji cloud-native. Już słyszę, jak część czytelników sobie myśli: „Jestem programistą – nie muszę się tym przejmować”, ale, proszę, powstrzymaj na chwilę swoje niedowierzanie. Praktyki operacyjne, które zapewniają spełnienie niektórych wymagań waszych klientów, bezpośrednio tłumaczą się na wymagania dla oprogramowania.

I ostatecznie, w trzecim rozdziale, omawiam platformy, które służą zarówno potrzebom programistycznym, jak i operatorskim. Wiele z wzorców, które omawiam w drugiej część książki, mimo że są absolutnie kluczowe dla wytwarzania oprogramowania najwyższej jakości, nie muszą być w całości przez ciebie implementowane; właściwa platforma może dostarczyć bardzo wiele wsparcia.

Jeśli więc kusi cię, by przeskoczyć tych kilka rozdziałów, proszę, nie rób tego. Obiecuję, że ta inwestycja się odpłaci w przyszłości.

1
Wciąż używasz tego słowa: definiując „cloud-native”

To nie wina Amazona. W niedzielę, 20 września 2015 roku Amazon Web Services (AWS) doświadczyło znaczącej awarii. Wraz z rosnącą liczbą firm utrzymujących na platformie AWS swoje krytyczne systemy, a nawet podstawowe usługi dostarczane klientom, jej awaria może doprowadzić do kolejnych, daleko idących przestojów systemów. W tym przypadku Netflix, Airbnb, Nest, IMDb i wiele innych firm doświadczyło przestoju wpływającego na ich klientów, a ostatecznie – na ich przychody. Awaria rdzennych części systemu trwała ponad pięć godzin (lub jeszcze dłużej, w zależności od tego, jak je liczyć), co u klientów korzystających z tych usług spowodowało jeszcze dłuższe awarie, zanim ich własne systemy powróciły do stabilnej pracy.

Firma Nest[*] płaci AWS, ponieważ chce skupić się na dostarczaniu wartości dla swoich klientów, a nie na utrzymywaniu infrastruktury. Częścią umowy jest zapis, że AWS odpowiada za utrzymanie działania swoich systemów, co pozwala również twoim systemom domowym działać poprawnie. Jeśli AWS doświadcza przestoju, wydaje się, że łatwo go obwinić za przerwy w działaniu twojego produktu.

Ale to byłby błąd. Amazon nie ponosi winy za twoje problemy.

Zaczekaj! Nie wyrzucaj jeszcze tej książki. Wysłuchaj mnie do końca. To zdanie dotyka sedna problemu i tłumaczy cel tego przedsięwzięcia.

Po pierwsze, pozwól mi wyjaśnić jedną rzecz. Nie sugeruję, że Amazon czy inni dostawcy usług chmurowych nie ponoszą odpowiedzialności za utrzymanie działania swoich systemów – oczywiście że ponoszą. A jeśli dostawca nie dopełnia pewnych umów dotyczących poziomu swoich usług (Service Level Agreements – SLA), jego klienci mogą poszukać i znajdą alternatywnych dostawców. Dostawcy usług udostępniają umowy o poziomie usług – na przykład Amazon gwarantuje dostępność większości swoich usług przez 99,95% czasu.

Ja twierdzę, że aplikacja, którą uruchamiasz na jakiejś infrastrukturze, może być bardziej stabilna niż sama infrastruktura. Jak to możliwe? Tego dokładnie, mój przyjacielu, nauczy cię ta książka.

Wróćmy na chwilę do awarii AWS z 20 września. Netflix był jedną z wielu firm, które zostały dotknięte tym przestojem, a jest to największa platforma internetowa w Stanach Zjednoczonych, biorąc pod uwagę zużycie przepustowości internetu (36%!). Jego błędy wpływają na bardzo wielu ludzi. Ale sprawdźmy, co Netflix miał do powiedzenia o awarii:

Netflix doświadczył krótkiej przerwy działania w dotkniętym awarią regionie, ale uniknęliśmy znaczącego wpływu na pracę, ponieważ ćwiczenia z wykorzystaniem narzędzia Chaos Kong przygotowały nas na takie zdarzenia. Dzięki regularnemu wykonywaniu symulacji wyłączeń całego regionu możemy wcześniej identyfikować i naprawiać wszelkie słabości naszego systemu. Kiedy US-EAST-1[**] stał się niedostępny, nasz system był już wystarczająco stabilny, aby obsłużyć awaryjne przeniesienie obsługi ruchu”[1].

Netflix był w stanie szybko wstać z kolan po awarii i być w pełni funkcjonalny w kilka minut po tym, jak incydent się rozpoczął. Netflix, wciąż działający na AWS, był całkowicie sprawny mimo trwającej awarii AWS.

UWAGA Jak im się to udało? Dzięki redundancji.

Aplikacje działają wewnątrz stref dostępności i, co ważne, mogą działać w więcej niż jednej strefie dostępności (AZ) i więcej niż jednym regionie (rys. 1.1). Przypomnij sobie, jak przed chwilą stwierdziłam, że redundancja jest jednym z kluczowych elementów dostępności usługi.

Rysunek 1.1. AWS partycjonuje oferowane usługi na regiony i strefy dostępności (AZ). Regiony mapują się na obszary geograficzne, a strefy dostępności dostarczają dalszej redundancji i izolacji w obszarze jednego regionu

Na rysunku 1.2 umieśćmy kilka logotypów, aby hipotetycznie zaprezentować działające aplikacje (nie mam dokładnej wiedzy o tym, jak Netflix, IMDb czy Nest wdrożyły swoje aplikacje; to w pełni przypuszczalne, ale mimo wszystko obrazujące problem).

Rysunek 1.2. Aplikacje uruchomione na AWS mogą być umieszczone w jednej strefie dostępności (IMDb), wielu strefach, ale w jednym regionie (Nest) lub w wielu strefach i wielu regionach (Netflix). To gwarantuje różne profile odporności na awarie

Rysunek 1.3 przedstawia awarię pojedynczego regionu, taką jaka wystąpiła we wrześniu 2015 roku, kiedy tylko region us-east-1 przestał odpowiadać.

Rysunek 1.3. Jeśli aplikacje są poprawnie zaprojektowane i wdrożone, cyfrowe rozwiązania mogą przetrwać nawet szeroko zakrojone awarie, jak na przykład całego regionu

Na tej prostej grafice możemy natychmiast zauważyć, dlaczego Netflix mógł przetrwać awarię o wiele lepiej niż inne firmy; aplikacja już działała w innych regionach AWS i łatwo można było przekierować cały ruch na inne, zdrowe instancje. I mimo że, jak się wydaje, awaryjne przekierowanie nie było automatyczne, Netflix oczekiwał (a także ćwiczył obsługę!) możliwych awarii takich jak ta i zaprojektował oprogramowanie i procedury operacyjne, by je skompensować[2].

UWAGA Oprogramowanie cloud-native jest zaprojektowane tak, by oczekiwać awarii i pozostać stabilnym nawet wtedy, gdy infrastruktura, na której działa, doświadcza awarii lub zmienia się w inny sposób.

Twórcy aplikacji, a także zespoły wsparcia i operatorskie muszą poznać i stosować w praktyce nowe wzorce i praktyki, by tworzyć i zarządzać oprogramowaniem cloud-native, a ta książka uczy właśnie tego. Możesz myśleć, że to nie jest nic nowego, iż organizacje, szczególnie w krytycznych strefach biznesu, takich jak finanse, operowały systemami aktywny–aktywny już od dawna, i masz rację. Ale to, co jest nowe, to sposób, w jaki się to osiąga.

W przeszłości wdrożenie takich awaryjnych przełączeń było właściwie szytym na miarę rozwiązaniem, przybitym gwoździami do procedur wdrożeń systemu, który nie był początkowo zaprojektowany do dostosowywania się do awarii. Wiedza o tym, jak osiągnąć wymagane poziomy dostępności usług, była często ograniczona do kilku „gwiazd rocka” i niezwykły design, konfiguracje i mechanizmy testowania były rozmieszczone w systemie, aby spróbować zmusić systemy do odpowiedniego zachowania w przypadku awarii.

Różnica między tym a praktykami, które Netflix stosuje dzisiaj, zaczyna się od fundamentalnej różnicy w filozofii. W poprzednich podejściach zmiana lub awaria są traktowane jako wyjątek od reguły. Tu przeciwnie, Netflix i inne firmy o dużej skali istniejące w internecie, takie jak Google, Twitter, Facebook czy Uber, traktują zmianę jako regułę. Te organizacje zmieniły architektury swojego oprogramowania i swoje praktyki inżynierskie, by sprawić, że projektowanie na niepowodzenia stanie się integralną częścią tego, jak budują, dostarczają i zarządzają oprogramowaniem.

UWAGA Ponieważ niepowodzenia są regułą, a nie wyjątkiem.

1.1. Wymagania dzisiejszych aplikacji

Cyfrowe doświadczenia już nie są dodatkiem do naszego życia, odgrywają znaczącą rolę w większości naszych codziennych aktywności. Ta wszechobecność przesunęła granice oczekiwań co do oprogramowania, którego używamy – chcemy, aby było zawsze dostępne, wciąż aktualizowane o nowe, bombowe funkcjonalności i dostarczało nam spersonalizowanych doświadczeń. Spełnianie tych oczekiwań to coś, co musi być adresowane od samego początku cyklu życia oprogramowania od pomysłu do produkcji – ty, programista, jesteś jedną ze stron odpowiedzialnych za ich spełnienie. Spójrzmy na kilka decydujących wymagań.

1.1.1. Brak przestojów

Awaria AWS z 20 września 2015 roku prezentuje jedno z istotnych wymagań dla nowoczesnej aplikacji: musi być zawsze dostępna. Minęły już czasy, gdy nawet krótkie okna serwisowe, podczas których aplikacje były nieosiągalne, są tolerowane – świat jest wciąż online. I mimo że nieplanowane przestoje nigdy nie były pożądane, ich wpływ osiągnął zadziwiający poziom. Na przykład w 2013 roku Forbes oszacował, że amazon.com stracił prawie 2 miliony dolarów podczas nieplanowanego, 13-minutowego przestoju[3]. Przerwy w działaniu, zaplanowane czy też nie, oznaczają znaczący spadek przychodów i niezadowolenie klientów.

Ale utrzymanie czasu działania nie jest problemem jedynie zespołu operacyjnego. Programista czy architekt oprogramowania jest odpowiedzialny za stworzenie designu systemu, gdzie luźno powiązane komponenty mogą być wdrażane, pozwalając na kompensacje nieuniknionych awarii przez redundancję i separację, która pozwoli powstrzymać awarie przed kaskadowym propagowaniem się przez system. Musi także zaprojektować oprogramowanie tak, aby wspierać wykonanie bez przestojów planowanych zdarzeń, takich jak aktualizacje.

1.1.2. Skrócone cykle informacji zwrotnej

Kolejną krytycznie ważną rzeczą jest możliwość częstego wydawania nowych wersji kodu. Napędzane przez znaczącą konkurencję i zawsze rosnące oczekiwania klientów aktualizacje aplikacji są udostępniane klientom kilka razy w miesiącu, wiele razy w tygodniu, a w pewnych sytuacjach nawet kilka razy dziennie. Ekscytacja klientów jest niewątpliwie ważna, ale być może największą motywacją tych ciągłych wydań jest zmniejszenie ryzyka.

Od momentu, gdy mamy pomysł na funkcjonalność, podejmujemy na pewnym poziomie ryzyko. Czy to dobry pomysł? Czy klienci będą w stanie go używać? Czy można to zaimplementować w wydajniejszy sposób? Mimo największych starań przewidzenia możliwych rezultatów rzeczywistość jest często różna od naszych oczekiwań. Najlepszym sposobem na uzyskanie odpowiedzi na ważne pytania, takie jak wspomniane, jest wydanie wczesnej wersji funkcjonalności i zebranie zwrotnych informacji. Używając ich, możemy dokonać poprawek lub nawet całkowicie zmienić kierunek naszych działań. Częste wydania oprogramowania skracają pętlę informacji zwrotnych i zmniejszają ryzyko.

Monolityczne systemy oprogramowania, które dominowały przez kilka ostatnich dekad, nie mogą być wydawane wystarczająco często. Zbyt wiele ściśle powiązanych ze sobą podsystemów, zbudowanych i testowanych przez niezależne zespoły, musiało być testowanych jako całość, nim często delikatny proces paczkowania mógł zostać rozpoczęty. Jeśli defekt był znaleziony późno, w fazie testów integracyjnych, długi i pracochłonny proces rozpoczynał się na nowo. Konieczne są nowe architektury oprogramowania, by osiągnąć wymaganą zwinność w wydawaniu oprogramowania produkcyjnego.

1.1.3. Wsparcie urządzeń mobilnych i wielu urządzeń

W kwietniu 2015 roku Comscore, czołowa firma zajmująca się mierzeniem i analityką trendów technologicznych, wydał raport, który pokazywał, że po raz pierwszy użycie internetu za pomocą urządzeń mobilnych przewyższyło wykorzystanie w tym celu komputerów osobistych[4]. Dzisiejsze aplikacje muszą wspierać co najmniej dwie platformy mobilne, iOS i Androida, oraz komputery osobiste (które nadal stanowią znaczący odsetek używanych urządzeń).

Co więcej, użytkownicy coraz bardziej oczekują płynnego przejścia, przenosząc się z używaniem aplikacji między urządzeniami w ciągu dnia. Na przykład chcą oglądać film na swoim Apple TV, a następnie przejść do oglądania tego samego programu na urządzeniu mobilnym w pociągu na lotnisko. Co więcej, wzorce użytkowania na urządzeniach mobilnych są bardzo różne od tych na komputerze osobistym – na przykład banki muszą być w stanie obsłużyć częste, powtarzające się odświeżanie aplikacji na urządzeniu mobilnym przez użytkowników czekających na swoją wypłatę.

Projektowanie aplikacji w odpowiedni sposób jest istotne dla spełnienia tych wszystkich wymagań. Wewnętrzne usługi muszą być zaimplementowane w taki sposób, aby wspierać wszystkie urządzenia służące użytkownikom, a cały system musi się dostosowywać do powiększających się i wiążących żądań.

1.1.4. Połączone urządzenia – tak zwany internet rzeczy

Internet nie służy już jedynie do łączenia ludzi z systemami umieszczonymi w centrach danych i udostępnianymi z serwerowni. Dzisiaj miliardy urządzeń są połączone z internetem, co umożliwia zarządzanie czy wręcz kontrolowanie ich przez inne podłączone jednostki. Sam rynek domowej automatyzacji, który reprezentuje niewielką część połączonych urządzeń, wspólnie tworzących internet rzeczy (Internet of Things – IoT), jest szacowany na 53 miliardy dolarów wartości w 2022 roku[5].

Dom połączony z siecią ma sensory i zdalnie kontrolowane urządzenia, takie jak czujniki ruchu, kamery, inteligentne termostaty czy nawet systemy oświetlenia, i to wszystko jest bardzo tanie: po wysadzeniu rury podczas trzydziestostopniowego mrozu kilka lat temu zaczęłam od skromnego systemu, zawierającego podłączony do internetu termostat i kilka czujników temperatury – wydałam na to mniej niż 300 dolarów. Do innych inteligentnych urządzeń należą samochody, sprzęt AGD, sprzęt rolniczy, silniki odrzutowe i superkomputer, który większość z nas nosi w kieszeni (smartfon).

Urządzenia połączone z internetem zmieniają naturę oprogramowania, które tworzymy, na dwa fundamentalne sposoby. Po pierwsze, ilość danych przepływających przez internet jest drastycznie zwiększona. Miliardy urządzeń nadają dane wiele razy na minutę, a nawet wiele razy na sekundę[6]. Po drugie, aby przechwycić i przetworzyć takie olbrzymie ilości danych, moc platformy obliczeniowej musi być znacząco różna niż w przeszłości. Obliczenia stają się dużo bardziej rozproszone, biorąc pod uwagę, że urządzenia je wykonujące są coraz bliżej „krawędzi”[***] sieci – miejsca, gdzie znajduje się połączone z nią urządzenie. Ta różnica w objętości danych i architekturze infrastruktury wymusza nowy design oprogramowania i nowe praktyki.

1.1.5. Kierowane danymi (data-driven)

Rozważanie kilku z wymagań, które zaprezentowałam do teraz, skłania do myślenia o danych w sposób bardziej holistyczny. Objętości danych rosną, ich źródła stają się coraz bardziej rozproszone, a cykle dostarczania oprogramowania – coraz krótsze. W połączeniu te trzy czynniki sprawiają, że duża, scentralizowana i współdzielona baza danych staje się nieużywalna.

Na przykład: silnik odrzutowy z setką czujników jest często odłączony od centrów danych zawierających takie bazy danych, a ograniczenia przepustowości nie pozwolą na transmisję wszystkich danych w krótkich oknach, kiedy łączność jest ustanawiana. Co więcej, współdzielone bazy danych wymagają dużej dozy procesów i koordynacji między wieloma aplikacjami, żeby zracjonalizować zróżnicowane modele danych i scenariusze integracji, co jest znaczącym utrudnieniem dla skróconych cyklów wydawniczych oprogramowania.

Zamiast jednej, współdzielonej bazy danych, te ograniczenia wymagają sieci mniejszych, lokalnych baz danych i oprogramowania, która zarządza zależnościami danych w tej federacji systemów zarządzania danymi. Te nowe podejścia kierują potrzebę zwinnego tworzenia oprogramowania i zarządzania wprost do warstwy danych.

Ostatecznie wszystkie te nowo dostępne dane mają niewielką wartość, jeśli nie są używane. Dzisiejsze aplikacje są coraz częściej zmuszone do używania danych, by dostarczać większą wartość do klienta przez ich efektywniejsze zastosowania. Na przykład aplikacje map wykorzystują dane GPS z połączonych samochodów i urządzeń mobilnych w zestawie z informacjami drogowymi i danymi o terenie, aby dostarczyć raporty o ruchu drogowym w czasie rzeczywistym i pomóc w wyszukiwaniu trasy. Aplikacje z przeszłych dekad, które implementowały pieczołowicie zaprojektowane algorytmy, ostrożnie dostosowywane do oczekiwanych scenariuszy użycia, są teraz zastępowane przez aplikacje, które są ciągle zmieniane lub nawet mogą same dostosowywać swoje wewnętrzne algorytmy i konfiguracje.

Te wymagania użytkownika – ciągła dostępność, ciągła ewolucja z częstymi wydaniami, łatwa skalowalność i inteligencja – nie mogą być zaspokojone z designem oprogramowania i systemami zarządzania z przeszłości. Ale co charakteryzuje oprogramowanie, które może sprostać tym wymaganiom?

1.2. Wprowadzenie oprogramowania cloud-native

Twoje oprogramowanie musi być dostępne 24/7. Musisz być w stanie często wydawać nowe wersje, by dostarczyć użytkownikom natychmiastową nagrodę, której oczekują. Mobilność i stan ciągłej łączności użytkowników zmuszają twoje oprogramowanie do bycia responsywnym na większe i bardziej zmienne ilości zapytań niż kiedykolwiek wcześniej. A połączone urządzenia („rzeczy”) tworzą rozproszoną sieć danych o bezprecedensowej wielkości, która wymaga nowych podejść do przechowywania i przetwarzania informacji. Te potrzeby, wspólnie z dostępnością nowych platform, na których możesz uruchamiać swoje oprogramowanie, spowodowały bezpośrednio powstanie nowego architektonicznego stylu oprogramowania: oprogramowania natywnego dla chmury – cloud-native.

1.2.1. Definiując cloud-native

Co charakteryzuje oprogramowanie cloud-native? Przeanalizujmy wcześniejsze wymagania nieco głębiej i zobaczmy, dokąd prowadzą. Rysunek 1.4 podejmuje kilka pierwszych kroków, wymieniając wymagania u góry i pokazując związki przyczynowe, kierując się w dół. Prezentowana lista wyjaśnia szczegóły:

Rysunek 1.4. Wymagania użytkownika dotyczące oprogramowania kierują jego rozwój w kierunku dogmatów cloud-native odnośnie do architektury i zarządzania

- Oprogramowanie, które jest zawsze dostępne, musi być odporne na awarie infrastruktury i zmiany, tak planowane, jak i nieplanowane. Jako że kontekst, w którym działa, doświadcza nieuniknionych zmian, oprogramowanie musi być zdolne do adaptacji. Kiedy jest prawidłowo skonstruowane, wdrożone i zarządzane, kompozycja niezależnych części może ograniczyć zasięg rażenia dowolnej awarii, która wystąpi; to kieruje cię do modułowego projektowania aplikacji. A ponieważ wiesz, że żadna pojedyncza jednostka nie może zagwarantować, że nigdy nie zawiedzie, w designie aplikacji uwzględniasz redundancję.

- Twoim celem jest częste wydawanie aplikacji, a monolityczne oprogramowanie na to nie pozwala; zbyt wiele współzależnych części wymaga czasochłonnej i skomplikowanej koordynacji. W ostatnich latach zostało solidnie udowodnione, że oprogramowanie złożone z mniejszych, często luźniej powiązanych i niezależnie wydawanych komponentów (niekiedy zwanych mikroserwisami) pozwala na zwinniejszy model wydawania oprogramowania.

- Użytkownicy nie są już ograniczeni w korzystaniu z cyfrowych rozwiązań do czasu, który spędzają przed swoimi komputerami. Wymagają dostępu za pomocą urządzeń mobilnych, których używają 24/7. Także obiekty niebędące ludźmi, jak sensory czy kontrolery urządzeń, są podobnie zawsze podłączone do sieci. Oba z tych scenariuszy powodują ogromną falę zapytań i ilość danych, która może bardzo dynamicznie się zmieniać, a co za tym idzie – wymaga oprogramowania, które skaluje się dynamicznie i nadal działa prawidłowo.

Niektóre z tych cech mają architektoniczne implikacje: wynikowe oprogramowanie jest złożone z uruchomionych redundantnych, niezależnych komponentów. Inne cechy adresują praktyki zarządzania wykorzystywane do dostarczania cyfrowych produktów: wdrożenie musi się dostosować do zmieniającej się infrastruktury i fluktuacji ilości przetwarzanych danych. Biorąc ten zestaw cech jako całość, sprowadźmy tę analizę do konkluzji, zaprezentowanej na rysunku 1.5:

Rysunek 1.5. Zasady architektury i zarządzania prowadzą do rdzennych cech oprogramowania cloud-native: jest wysoko rozproszone i musi działać w nieustannie zmieniającym się środowisku, nawet gdy oprogramowanie wciąż ewoluuje

- Oprogramowanie, które jest stworzone jako zestaw niezależnych komponentów, niezależnie wdrażanych, implikuje rozproszenie elementów systemu. Gdyby twoje nadmiarowe kopie były uruchomione blisko siebie, byłoby większe ryzyko, że lokalne awarie miałyby daleko idące konsekwencje. Aby efektywnie wykorzystać zasoby infrastruktury, które posiadasz, uruchamiając dodatkowe instancje swojej aplikacji, żeby obsłużyć rosnącą ilość żądań, musisz mieć możliwość umieszczania ich na szerokiej powierzchni dostępnej sobie infrastruktury – nawet, być może, takiej od dostawców usług chmurowych, jak AWS, Google Cloud Platform (GCP) czy Microsoft Azure. Wskutek czego wdrażasz moduły swojego oprogramowania w wysoce rozproszony sposób.

- Oprogramowanie zdolne do adaptacji jest z definicji „zdolne do dostosowania się do nowych warunków” i warunki, do których się tu odnoszę, są związane z infrastrukturą i zestawem powiązanych ze sobą modułów oprogramowania. Są one wewnętrznie powiązane: wraz ze zmianą infrastruktury zmienia się oprogramowanie i vice versa. Częste wydania nowych wersji aplikacji oznaczają częste zmiany, a dostosowywanie się do fluktuacji ilości obsługiwanych żądań przez operacje skalowania reprezentują ciągłe dostosowywanie się. To jasne, że twoje oprogramowanie i środowisko, w którym ono działa, ciągle się zmieniają.

DEFINICJA Oprogramowanie cloud-native jest wysoko rozproszone, musi działać w nieustannie zmieniającym się środowisku i samo również wciąż się zmienia.

Wiele drobniejszych szczegółów wchodzi w skład procesu wytwarzania oprogramowania cloud-native (dokładne informacje wypełniają strony tej książki). Ale w ostatecznym rozrachunku wszystkie sprowadzają się do tych rdzennych cech: wysoko rozproszone i ciągle zmienne. To będzie twoją mantrą podczas zapoznawania się z materiałem, a ja wielokrotnie będę cię sprowadzać z powrotem do systemów ekstremalnie rozproszonych i ciągłych zmian.

1.2.2. Model myślowy dla oprogramowania cloud-native

Adrian Cockcroft, który był głównym architektem w Netfliksie, a teraz jest VP of Cloud Architecture Strategy w AWS, mówi o złożoności prowadzenia samochodu: jako kierowca musisz kontrolować samochód i nawigować po ulicach, w tym samym czasie starając się nie wejść w kontakt z innymi kierowcami, wykonującymi te same, skomplikowane zadania[7]. Jesteś w stanie to robić tylko dlatego, że stworzyłeś model, który pozwala ci zrozumieć świat i kontrolować swoje narzędzie (w tym przypadku samochód) w ciągle zmieniającym się środowisku.

Większość z nas używa swoich stóp, by kontrolować szybkość, i rąk, by ustalić kierunek, efektywnie określając swój wektor prędkości. Podejmując próbę usprawnienia nawigacji, planiści miast wprowadzili przemyślane układy miast (niech Bóg nam wszystkim pomoże w Paryżu). Narzędzia takie jak znaki i sygnalizacje drogowe w połączeniu z zasadami ruchu drogowego dają ci strukturę, w której możesz myśleć o swojej podróży od początku do końca.

Pisanie aplikacji cloud-native także jest złożone. W tej sekcji prezentuję model pozwalający wprowadzić porządek do mnóstwa zmartwień towarzyszących tworzeniu oprogramowania cloud-native. Mam nadzieję, że ten schemat ułatwi zrozumienie głównych konceptów i technik, co pozwoli ci zostać skutecznym architektem i programistą cloud-native.

Zacznę od łatwych rzeczy, rdzennych elementów oprogramowania tworzonego dla chmury, które na pewno znasz, przedstawionych na rysunku 1.6.

Rysunek 1.6. Znajome elementy podstawowej architektury oprogramowania

App (od application – aplikacja) implementuje zasadniczą logikę biznesową. To tutaj będziesz pisał większość kodu. To tutaj na przykład twój kod odbierze zamówienie od klienta, potwierdzi, że towar jest dostępny w zapasach magazynowych, i wyśle notyfikację do działu księgowego.

Aplikacja jest oczywiście zależna od innych komponentów, których używa, aby otrzymać informacje albo podjąć akcję; nazywam je usługami (services). Niektóre z tych usług przechowują stan – na przykład opis stanu magazynu. Inne mogą być aplikacjami implementującymi logikę biznesową dla innej części twojego systemu – na przykład fakturowania klienta.

Z wykorzystaniem tych prostych konceptów zbudujmy teraz topologię reprezentującą oprogramowanie cloud-native, które będziesz tworzyć – rysunek 1.7. Widzimy tutaj rozproszony zestaw modułów, z których większość ma wiele uruchomionych instancji. Można stwierdzić, że większość z tych aplikacji działa także jako usługi, i dalej, że niektóre z usług są wyraźnie stanowe. Strzałki opisują, jak komponenty zależą od innych.

Ten diagram ilustruje kilka interesujących elementów. Po pierwsze, zwróć uwagę, że elementy (prostokąty i ikony bazy danych lub pamięci trwałej) są zawsze opisane przez dwa oznaczenia: aplikacja i usługa dla prostokątów lub usługa i stan – dla ikonki dysku. Zaczęłam myśleć o prostych konceptach ukazanych na rysunku 1.7 jako o rolach, które przyjmują przeróżne komponenty w twoim oprogramowaniu.

Rysunek 1.7. Oprogramowanie cloud-native bierze znajome konwencje i dodaje ekstremalne rozproszenie systemu, z redundancją na każdym etapie i ciągłymi zmianami

Zauważ też, że każdy obiekt, który ma strzałkę kierującą do niego, oznaczającą, że jakiś inny komponent od niego zależy, jest usługą. To prawda – prawie wszystko jest usługą. Nawet aplikacja, która jest początkiem naszej topologii ma skierowaną do siebie strzałkę od konsumenta naszego oprogramowania. Aplikacje, oczywiście, są miejscem, gdzie działa twój kod. Poza tym szczególnie lubię połączenie adnotacji usługa i stan, co jasno podkreśla, że część usług jest pozbawiona stanu (bezstanowe usługi, o których na pewno słyszałeś, opisane tu jako aplikacje), podczas gdy celem istnienia innych jest zarządzanie stanem.

To sprowadza mnie do zdefiniowania trzech części aplikacji cloud-native, przedstawionych na rysunku 1.8:

Rysunek 1.8. Kluczowe obiekty w modelu oprogramowania cloud-native: aplikacje, dane i interakcje

- Aplikacja cloud-native – jeszcze raz: to jest miejsce, gdzie znajduje się twój kod, to logika biznesowa twojego oprogramowania. Implementacja odpowiednich wzorców w tym miejscu pozwala tym aplikacjom zachowywać się jak dobry obywatel społeczności stworzonej przez twoje oprogramowanie. Pojedyncza aplikacja rzadko jest kompletnym cyfrowym produktem. Aplikacja jest na jednym lub drugim końcu strzałki (lub obu), a zatem musi implementować pewne zachowanie, by mogła być częścią tej relacji. Musi także być skonstruowana w sposób, który umożliwi stosowanie odpowiednich praktyk operacyjnych, zgodnych z cloud-native, takich jak skalowanie i sposób aktualizacji do nowej wersji.

- Dane cloud-native – to tutaj żyje stan twojego oprogramowania cloud-native. Nawet ten prosty rysunek pokazuje wyraźne odchylenie od architektur z przeszłości, które często używały scentralizowanej bazy danych do przechowywania stanu dla znacznych części aplikacji. Na przykład: możliwe, że przechowywałeś profile użytkowników, informacje o kontach, opinie, historię zamówień, informacje o płatnościach i inne w tej samej bazie danych. Oprogramowanie cloud-native dzieli kod na wiele mniejszych modułów (aplikacji) i podobnie jest rozdzielona i rozproszona baza danych.

- Interakcje cloud-native – oprogramowanie cloud-native jest zatem połączeniem aplikacji i danych cloud-native, a sposób, w jaki te części współdziałają ze sobą, ostatecznie determinuje funkcjonowanie i cechy cyfrowego systemu. Z powodu ekstremalnego rozproszenia i ciągłych zmian, które charakteryzują nasz system, te interakcje w wielu sytuacjach znacząco wyewoluowały względem tych klasycznych architektur oprogramowania, a niektóre z wzorców zachowań są całkowicie nowe.

Przypisy

Rozdział 1

* Firma produkująca rozwiązania domów inteligentnych, obecnie wykupiona przez Google – przyp. tłum.

** Region AWS – przyp. tłum.

*** Tak zwany edge computing – wykonywanie obliczeń na urządzeniach końcowych – przyp. tłum.

1 Patrz też wpis „Chaos Engineering Upgraded” na blogu Netflix Technology (http://mng.bz/P8rn), by uzyskać więcej informacji o Chaos Kong.

2 Patrz też „AWS Outage: How Netflix Weathered the Storm by Preparing for the Worst”, autorstwa Nicka Heatha (http://mng.bz/J8RV), by poznać więcej szczegółów o procesie odtwarzania się firmy.

3 Patrz też „Amazon.com Goes Down, Loses $66240 Per Minute” autorstwa Kelly Clay na stronie Forbes (http://mng.bz/wEgP).

4 Patrz też blog Kate Dryer z 13 kwietnia 2015 roku na stronie Comscore (mng.bz/7eKv) zawierający podsumowanie raportu.

5 Możesz przeczytać więcej o tych odkryciach przez Zion Market Research na stronie GlobeNewswire (http://mng.bz/mm6a)

6 Gartner przewidywał, że 8,4 miliarda połączonych rzeczy będzie w użyciu w 2017 roku; raport Gartnera możesz znaleźć pod adresem: www.gartner.com/newsroom/id/3598917.

7 Posłuchaj Adriana mówiącego o tym i innych przykładach skomplikowanych operacji pod adresem http://mng.bz/5NzO.