Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00300 007028 19024369 na godz. na dobę w sumie
Tao mikrousług. Projektowanie i wdrażanie - książka
Tao mikrousług. Projektowanie i wdrażanie - książka
Autor: Liczba stron: 352
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-283-4807-3 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> inne - programowanie
Porównaj ceny (książka, ebook (-35%), audiobook).

Systemy oparte na mikrousługach różnią się od aplikacji monolitycznych. Są bardziej skalowalne, efektywniejsze, a także łatwiejsze w implementacji, rozwijaniu i utrzymaniu. Architektura mikrousług pozwala na doskonalenie danego elementu bez zastanawiania się nad działaniem całości aplikacji. Tego rodzaju systemy opierają się na nowoczesnych wzorcach, takich jak asynchroniczna komunikacja za pomocą komunikatów, usługi API i hermetyzacja. Po odpowiedniej optymalizacji dobrze działają zarówno w chmurach, jak i w scentralizowanych środowiskach opartych na kontenerach.

Niniejsza książka jest przeznaczona dla programistów, menedżerów projektów i architektów oprogramowania. Wyjaśniono tu niezbędne pojęcia oraz różnice dzielące systemy oparte na mikrousługach i aplikacje monolityczne, a także zasady ich projektowania. Wyczerpująco omówiono techniki rozwiązywania problemów z mikrousługami oraz sposoby kontrolowania ryzyka wystąpienia awarii. Pokazano, w jaki sposób mikrousługi mogą współpracować z trwałymi danymi i jak wygląda ich współpraca z bazami danych. Sporo miejsca poświęcono technikom oceny kondycji działających systemów mikrousługowych, a także studiom przypadków oraz najlepszym praktykom pracy zespołu, planowania zmian i wyboru narzędzi.

Najważniejsze zagadnienia:

Pracuj mądrzej i bardziej humanitarnie. Wdrażaj mikrousługi!

Znajdź podobne książki Ostatnio czytane w tej kategorii

Darmowy fragment publikacji:

Tytuł oryginału: The Tao of Microservices Tłumaczenie: Marcin Dzieszko ISBN: 978-83-283-4807-3 Original edition copyright © 2018 by Manning Publications All rights reserved. Polish edition copyright © 2019 by Helion SA All rights reserved. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher. Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną, fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje naruszenie praw autorskich niniejszej publikacji. Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich właścicieli. Autor oraz Helion SA dołożyli wszelkich starań, by zawarte w tej książce informacje były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Helion SA nie ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji zawartych w książce. Helion SA ul. Kościuszki 1c, 44-100 Gliwice tel. 32 231 22 19, 32 230 98 63 e-mail: helion@helion.pl WWW: http://helion.pl (księgarnia internetowa, katalog książek) Drogi Czytelniku! Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres http://helion.pl/user/opinie/taomik Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję. Printed in Poland. • Kup książkę • Poleć książkę • Oceń książkę • Księgarnia internetowa • Lubię to! » Nasza społeczność Przedmowa Podziękowania O książce O autorze O ilustracji na okładce CZĘŚĆ I. BUDOWANIE MIKROUSŁUG Rozdział 1. Odważny nowy świat 1.1. Kryzys długu technicznego 1.2. Studium przypadku: start-up mikroblogu 1.2.1. Iteracja 0.: publikowanie wpisów 1.2.2. Iteracja 1.: indeks wyszukiwania 1.2.3. Iteracja 2.: prosta kompozycja 1.2.4. Iteracja 3.: oś czasu 1.2.5. Iteracja 4.: skalowanie 1.3. Jak monolit sprzeniewierza się obietnicy komponentów 1.4. Idea mikrousługi 1.4.1. Podstawowe zasady techniczne 1.5. Praktyczne implikacje 1.5.1. Specyfikacja 1.5.2. Wdrożenie 1.5.3. Bezpieczeństwo 1.5.4. Ludzie 1.6. Co dostajesz za swoje pieniądze 1.7. Podsumowanie Rozdział 2. Usługi 2.1. Definicje mikrousług 2.2. Studium przypadku: wydanie cyfrowe gazety 2.2.1. Cele biznesowe 2.2.2. Wymagania nieformalne 2.2.3. Podział funkcjonalny 2.3. Architektury mikrousług 2.3.1. Architektura miniserwerów webowych 2.4. Diagramy mikrousług 2.5. Drzewo zależności mikrousług 2.5.1. Architektura komunikatów asynchronicznych Spis treści 11 13 15 19 21 23 25 25 28 28 32 35 37 40 43 45 47 51 51 52 54 55 56 57 59 60 62 62 62 63 64 65 66 67 71 Kup książkęPoleć książkę 6 Spis treści 2.6. Projekty monolityczne a projekty mikrousługowe 2.6.1. Jak mikrousługi zmieniają zarządzanie projektem 2.6.2. Jednolitość ułatwia estymację 2.6.3. Jednorazowy kod tworzy bardziej przyjazne zespoły 2.6.4. Homogeniczne komponenty pozwalają na heterogeniczną konfigurację 2.6.5. Istnieją różne rodzaje kodów 2.7. Jednostka oprogramowania 2.8. Wymagania dotyczące komunikatów do usług 2.9. Diagramy architektury mikrousług 2.9.1. Diagramy przepływów komunikatów 2.10. Mikrousługi to komponenty oprogramowania 2.10.1. Enkapsulacja 2.10.2. Wielokrotne użycie 2.10.3. Dobrze zdefiniowane interfejsy 2.10.4. Kompozycyjność 2.10.5. Mikrousługi jako komponenty w praktyce 2.11. Wewnętrzna struktura mikrousługi 2.12. Podsumowanie Rozdział 3. Komunikaty 3.1. Komunikaty są obywatelami pierwszej klasy 3.1.1. Synchroniczne i asynchroniczne 3.1.2. Kiedy używać komunikacji synchronicznej 3.1.3. Kiedy używać komunikacji asynchronicznej 3.1.4. Rozproszone myślenie od pierwszego dnia 3.1.5. Taktyki ograniczające awarie 3.2. Analiza przypadku: obliczanie podatku od sprzedaży 3.2.1. Szerszy kontekst 3.3. Dopasowanie do wzorca 3.3.1. Podatek od sprzedaży: prosty początek 3.3.2. Podatek od sprzedaży: obsługa kategorii 3.3.3. Podatek od sprzedaży: obsługa przypadków globalnych 3.3.4. Wymagania biznesowe zmieniają się z definicji 3.3.5. Dopasowanie do wzorca obniża koszt refaktoryzacji 3.4. Niezależność od transportu 3.4.1. Przydatna fikcja: wszechmocny obserwator 3.5. Wzorce komunikatów 3.5.1. Wzorce bazowe: jeden komunikat/dwie usługi 3.5.2. Wzorce bazowe: dwa komunikaty/dwie usługi 3.5.3. Wzorce bazowe: jeden komunikat/n usług 3.5.4. Wzorce bazowe: m komunikatów/n usług 3.5.5. m/n: Łańcuch 3.5.6. m/n: Drzewo 3.5.7. Skalowanie komunikatów 3.6. Gdy komunikaty się zepsują 3.6.1. Typowe scenariusze awarii i co z nimi robić 3.6.2. Awarie dominujące w interakcji Żądanie-Odpowiedź 3.6.3. Awarie dominujące w interakcji Pocisk Samonaprowadzający 73 75 75 76 77 78 79 80 83 85 87 87 87 88 88 89 91 92 93 93 95 96 98 98 100 102 102 103 104 106 109 109 110 111 112 112 113 116 118 121 121 122 122 124 125 125 126 Kup książkęPoleć książkę Spis treści 7 3.6.4. Awarie dominujące w interakcji Zwycięzca Bierze Wszystko 3.6.5. Awarie dominujące w interakcji Uruchom i Zapomnij 3.7. Podsumowanie Rozdział 4. Dane 4.1. Dane nie oznaczają tego, co Twoim zdaniem oznaczają 4.1.1. Dane są heterogeniczne, a nie homogeniczne 4.1.2. Dane mogą być prywatne 4.1.3. Dane mogą być lokalne 4.1.4. Dane mogą być jednorazowe 4.1.5. Dane nie muszą być dokładne 4.2. Strategie danych dla mikrousług 4.2.1. Używanie komunikatów do ujawniania danych 4.2.2. Używanie kompozycji do manipulowania danymi 4.2.3. Używanie konfiguracji systemu do kontrolowania danych 4.2.4. Nałożenie słabszych ograniczeń na dystrybucję danych 4.3. Ponowne przemyślenie tradycyjnych wzorców danych 4.3.1. Klucze podstawowe 4.3.2. Klucze obce 4.3.3. Transakcje 4.3.4. Transakcje nie są tak dobre, jak Ci się wydaje 4.3.5. Schematy zaciągają dług techniczny 4.4. Praktyczny przewodnik decyzyjny dotyczący danych z mikrousług 4.4.1. Projekty od podstaw 4.4.2. Projekty zastane 4.5. Podsumowanie Rozdział 5. Wdrażanie 5.1. Rzeczy się rozpadają 5.2. Nauka z historii 5.2.1. Three Mile Island 5.2.2. Model awarii w systemach oprogramowania 5.2.3. Redundancja nie działa tak, jak myślisz 5.2.4. Zmiana jest przerażająca 5.3. Centrala nie daje rady 5.3.1. Koszt doskonałego oprogramowania 5.4. Anarchia działa 5.5. Mikrousługi i redundancja 5.6. Ciągłe dostarczanie 5.6.1. System wdrażania 5.6.2. Proces 5.6.3. Ochrona 5.7. Uruchomienie systemu mikrousługowego 5.7.1. Niezmienność 5.7.2. Automatyzacja 5.7.3. Wytrzymałość 5.7.4. Walidacja 5.7.5. Wykrywanie usług 5.7.6. Konfiguracja 127 128 129 131 132 132 134 135 137 138 138 138 140 144 149 151 151 152 153 157 159 160 161 162 163 165 166 167 167 172 176 177 180 181 181 182 183 185 186 187 188 188 191 196 201 204 205 Kup książkęPoleć książkę 8 Spis treści 5.7.7. Bezpieczeństwo 5.7.8. Środowisko pomostowe 5.7.9. Rozwój oprogramowania 5.8. Podsumowanie CZĘŚĆ II. MIKROUSŁUGI W AKCJI Rozdział 6. Wdrażanie 6.1. Granice tradycyjnego monitoringu 6.1.1. Klasyczne konfiguracje 6.1.2. Problem z wartościami przeciętnymi 6.1.3. Używanie percentyli 6.1.4. Konfiguracje mikrousług 6.1.5. Potęga wykresów punktowych 6.1.6. Tworzenie panelu nawigacyjnego 6.2. Pomiary dla mikrousług 6.2.1. Warstwa biznesowa 6.2.2. Warstwa komunikatów 6.2.3. Warstwa usługi 6.3. Siła niezmienników 6.3.1. Wyszukiwanie niezmienników w logice biznesowej 6.3.2. Wyszukiwanie niezmienników w architekturze systemu 6.3.3. Wizualizacja niezmienników 6.3.4. Odkrywanie systemu 6.3.5. Walidacja syntetyczna 6.4. Podsumowanie Rozdział 7. Migracja 7.1. Klasyczny przykład witryny e-commerce 7.1.1. Dotychczasowa architektura 7.1.2. Proces dostarczania oprogramowania 7.2. Przesuwanie słupków bramki 7.2.1. Praktyczne zastosowanie polityki 7.3. Rozpoczęcie podróży 7.4. Taktyka dusiciela 7.4.1. Częściowe proxy 7.4.2. Co robić, gdy nie można przeprowadzić migracji 7.4.3. Taktyka budowania od podstaw 7.4.4. Taktyka makrousługi 7.5. Strategia doskonalenia 7.6. Przejście od ogólnego do konkretnego 7.6.1. Dodawanie funkcjonalności do strony produktu 7.6.2. Dodawanie funkcjonalności do koszyka 7.6.3. Obsługiwanie zagadnień przekrojowych 7.7. Podsumowanie 206 207 208 210 211 213 214 215 217 218 221 221 223 224 224 225 233 237 238 239 241 242 244 245 247 248 248 250 251 254 255 256 257 258 260 263 265 266 266 269 271 272 Kup książkęPoleć książkę Spis treści 9 Rozdział 8. Ludzie 8.1. Radzenie sobie z polityką organizacji 8.1.1. Akceptowanie twardych ograniczeń 8.1.2. Wyszukiwanie sponsorów 8.1.3. Budowanie sojuszy 8.1.4. Dostarczanie skoncentrowane na wartości 8.1.5. Dopuszczalne wskaźniki błędów 8.1.6. Odrzucanie funkcjonalności 8.1.7. Zatrzymanie abstrahowania 8.1.8. Oczyszczanie umysłów z uprzedzeń 8.1.9. Walidacja zewnętrzna 8.1.10. Solidarność zespołowa 8.1.11. Szanuj organizację 8.2. Polityka wynikająca ze stosowania mikrousług 8.2.1. Kto jest właścicielem i czego? 8.2.2. Kto jest pod telefonem? 8.2.3. Kto decyduje, co kodować? 8.3. Podsumowanie Rozdział 9. Studium przypadku: nodezoo.com 9.1. Projektuj 9.1.1. Czym są wymagania biznesowe? 9.1.2. Czym są komunikaty? 9.1.3. Czym są usługi? 9.2. Dostarczaj 9.2.1. Iteracja 1.: rozwój lokalny 9.2.2. Iteracja 2.: testowanie, instalacja w systemie pomostowym i pomiar ryzyka 9.2.3. Iteracja 3.: droga do środowiska produkcyjnego 9.2.4. Iteracja 4.: poprawki i adaptacja 9.2.5. Iteracja 5.: monitorowanie i debugowanie 9.2.6. Iteracja 6.: skalowanie i wydajność 9.3. Odważny nowy świat Skorowidz 275 276 276 277 279 280 280 280 281 282 282 283 284 284 285 286 288 292 295 296 296 298 304 309 310 322 327 332 339 342 346 349 Kup książkęPoleć książkę 10 Spis treści Kup książkęPoleć książkę Usługi Niniejszy rozdział opisuje zagadnienia:  udoskonalenie koncepcji mikrousług,  przegląd głównych wariantów architektury mikrousług,  porównanie monolitów z mikrousługami,  użycie konkretnego przypadku do zbadania mikrousług,  myślenie o mikrousługach jak o komponentach oprogramowania. Aby być świadomym konsekwencji i kompromisów związanych z przejściem do no- wej architektury, musisz zrozumieć, w jaki sposób różni się ona od poprzedniej ar- chitektury oraz jak nowe metody rozwiązują dawne problemy. Jakie są istotne różni- ce między architekturą monolityczną a architekturą opartą na mikrousługach? Jakie są nowe sposoby myślenia? I wreszcie jak mikrousługi rozwiązują problemy rozwoju oprogramowania korporacyjnego? Mikrousługa to jednostka rozwoju oprogramowania. Architektura mikrousługi two- rzy model mentalny, który umożliwia postrzeganie zagadnienia w uproszczony sposób. Książka ta przedstawia mikrousługi jako komponenty oprogramowania najbliższe ide- ałowi. Są to idealne artefakty do precyzyjnego zastosowania w produkcji. Łatwo oszaco- wać ich ilość, aby zapewnić prawidłowe działanie. Podstawą mikrousług jest przekona- nie, że powyższe aspekty ich architektury zapewniają szybki, praktyczny i skuteczny sposób tworzenia wartości biznesowej za pomocą oprogramowania. Przyjrzyjmy się szcze- gółom, aby zobaczyć, jak to działa w praktyce. Kup książkęPoleć książkę 60 ROZDZIAŁ 2. Usługi 2.1. Definicje mikrousług Termin mikrousługa jest z natury rozmyty. Jest to społeczny skutek rosnącej popu- larności tej architektury. Kiedy używamy wspomnianego terminu, powinniśmy spre- cyzować, jak go rozumieć. W znacznej części artykułów na temat mikrousług wyra- żany jest taki sam stosunek do rozwoju oprogramowania, ale używa się w nich różnych definicji tego kluczowego pojęcia. Akceptowanie wielu słabych definicji z kolei ogra- nicza nasze myślenie i stanowi łatwy cel krytyki. Przeanalizujmy kilka proponowa- nych definicji:  Mikrousługi są samodzielnymi komponentami oprogramowania, które mają nie więcej niż 100 linii kodu. Ta definicja oddaje chęć tworzenia małych mikrousług utrzymywanych przez jednego programistę, a nie przez cały zespół. To odwołanie do idei, że ekstremalna prostota ma ekstremalne zalety: 100 linii kodu może być szybko i pewnie sprawdzone pod kątem błędów1. Niewielki fragment kodu można również w razie potrzeby łatwo usunąć i przepisać na nowo. Są to pożądane cechy w przypadku mikrousług, ale nie wyczerpuje to wszystkich zagadnień. Na przykład nie są podniesione kwestie dotyczące wdrażania i komunikacji między usługami. Podstawową słabością tej definicji jest również użycie arbitralnego ograniczenia liczby linii kodu, które traci sens, jeśli zmienimy język programowania. Ponieważ rozważamy inne definicje, zachowajmy pragnienie tworzenia kodu usługi wystarczająco niewielkiego, aby łatwo można go było zweryfikować i wyrzucić, jeśli zajdzie taka potrzeba.  Mikrousługi są wdrażanymi niezależnie procesami komunikującymi się asynchronicznie przy użyciu lekkich mechanizmów; skupiają się na konkretnych możliwościach biznesowych oraz działają w zautomatyzowanym środowisku, niezależnie od platformy i użytych języków. Część definicji mikrosystemów ma charakter ogólny, zawierając wszystkie możliwe aspekty. Te definicje posiadają długą listę pożądanych atrybutów. Czy te atrybuty są uporządkowane według ważności? Czy ich lista jest wyczerpująca? Czy są dobrze zdefiniowane? Ogólne definicje dają poczucie, jakbyś był w odpowiedniej galaktyce, ale nie zapewniają wskazówki, jak dostać się do systemu mikrousługi. Zapraszają do niekończącej się debaty nad definicjami atrybutów. Czym, na przykład, jest naprawdę lekki mechanizm komunikacji?2 To, co możemy wziąć z tych definicji, 1 C. A. R. Hoare, twórca algorytmu quicksort, w swoim wykładzie z okazji otrzymania Nagrody Turinga (Turing Award Lecture) w 1980 r. wypowiedział słynne zdanie: „Istnieją dwa sposoby tworzenia projektu oprogramowania: jednym z nich jest uczynienie go tak prostym, że oczywiście nie ma w nim żadnych braków, a innym sposobem jest uczynienie go tak skomplikowanym, że nie ma w nim oczywistych braków”. 2 Niemożliwe jest wygranie wojny definicji. Gdy tylko przedstawisz ostateczny kontrprzykład, Twój przeciwnik zaprzeczy, że tenże jest w rzeczywistości przykładem dotyczącym omawianego tematu. Brytyjski filozof Antony Flew dostarcza kanonicznego przykładu tej taktyki, którą można sparafrazować w następujący sposób — Robert: „Wszyscy Szkoci noszą kilt!”; Hamish: „Mój wujek Duncan nosi spodnie”; Robert: „Tak, ale żaden prawdziwy Szkot tak nie robi”. Kup książkęPoleć książkę 2.1. Definicje mikrousług 61 to działający zestaw pomysłów, które można wykorzystać w praktyce, ale które same z siebie nie zapewniają wystarczającej przejrzystości.  Mikrousługi to miniserwery webowe oferujące niewielkie API, które akceptują i zwracają dokumenty typu JSON. Jest to z pewnością powszechna implementacja. I to są rzeczywiście mikrousługi. Ale jak duże one są? I w jaki sposób ta definicja odnosi się do wszystkich innych problemów, takich jak niezależne wdrażanie? Ta definicja jest jednocześnie zbyt normatywna w niektórych kwestiach i niewystarczająco normatywna w innych. To definicja według pewnego archetypu. Niewielu nie zgodziłoby się z tym, że są to mikrousługi. A jednak wykluczona tu została większość ciekawych wzorów architektonicznych, w szczególności tych, które korzystają z asynchronicznych komunikatów. Ta definicja jest nie tylko słaba, ale również i niebezpieczna. Dowody empiryczne z wdrożonych systemów u klienta sugerują, że często taki model prowadzi do silnie powiązanych usług, które muszą być wdrożone razem3. Kluczowy wniosek z tej nieudanej definicji jest taki, że ograniczanie się do myślenia tylko w kategoriach API usług webowych uniemożliwia nam docenianie zasadniczych możliwości, które może przynieść szersza koncepcja. Definicja powinna pobudzać nasze myślenie, a nie je ograniczać.  Mikrousługa to niezależny komponent oprogramowania, na którego zbudowanie i wdrożenie potrzeba nie więcej niż jednej iteracji. W tej definicji nacisk kładziony jest na ludzką stronę architektury. Wyrażenie niezależny komponent oprogramowania jest sugestywne i na tyle obszerne, że definicja ta stara się również zawierać strategie implementacji. Mikrousługi to komponenty oprogramowania wykorzystujące powszechne zrozumienie tego terminu4. Definicja ta wyraża pragnienie, aby mikrousługi rzeczywiście były „mikro” poprzez ograniczenie zasobów potrzebnych do ich napisania: jedna iteracja to wszystko, w co musisz zainwestować. Jest to ukłon w stronę stałego dostarczania — musisz być w stanie wdrożyć komponent w ciągu iteracji. Definicja ta jest ostrożna, unika wzmianek dotyczących procesów systemu operacyjnego, sieci, przetwarzania rozproszonego i protokołów komunikatów; żadne z nich nie jest esencjonalną właściwością5. Musimy zaakceptować fakt, że nie jesteśmy dziećmi w wieku szkolnym, ale profesjo- nalnymi programistami, i że żyjemy w skomplikowanym świecie dorosłych. Nie ma uporządkowanej definicji mikrousług, a każda wybrana przez nas definicja ogranicza 3 W moim poprzednim wcieleniu konsultanta kierowałem swoimi biednymi zespołami tak, aby zbudowały wiele dużych systemów. Związaliśmy się najwspanialszymi węzłami gordyjskimi. 4 Komponenty oprogramowania to niezależne, rozszerzalne, dobrze zdefiniowane bloki konstrukcyjne wielokrotnego użytku. 5 Procesy Erlanga to z pewnością mikrousługi lub, co być może jest bardziej poprawne, nanousługi! Usilnie zalecam Ci przeczytanie doktoratu Joe’ego Armstronga, w którym opisano wszystkie szczegóły: Making Reliable Distributed Systems in the Presence of Software Errors, Royal Institute of Technology, 2003, http://erlang.org/download/armstrong_thesis_2003.pdf. Kup książkęPoleć książkę 62 ROZDZIAŁ 2. Usługi nasze myślenie. Zamiast więc szukać definicji, która zależy od parametrów liczbowych lub próbuje być wyczerpująca albo, na odwrót, zbyt wyspecjalizowana, powinniśmy dążyć do opracowania struktury koncepcyjnej, która jest wytwórcza. Pojęcia w ramach tej struktury pozwolą na dokładne zrozumienie nieodłącznych kompromisów związa- nych z architekturą mikrousługi. Następnie zastosujemy te pojęcia w danym kontek- ście, aby dostarczyć działające oprogramowanie6. 2.2. Studium przypadku: wydanie cyfrowe gazety Większość rozdziałów w tej książce wykorzystuje studium przypadku, aby poddać pod dyskusję praktyczne przykłady opisywanych pojęć. Poddane analizie będą systemy oprogramowania, które muszą dostarczyć szereg funkcjonalności; w każdym rozdziale zastanowimy się, jak architektura mikrousług może je implementować. Dla każdego systemu skoncentrujemy się na podzbiorze tych funkcjonalności, które dotyczą tematu omawianego w danym rozdziale. Rozdział 9. to pełne studium przypadku, w tym kod, który stanowi praktyczny przykład systemu mikrousług z wykorzystaniem technik architektonicznych opracowanych w tej książce. Nasze studium w tym rozdziale dotyczy cyfrowej edycji gazety. Opiszmy ten sys- tem dokładnie, zaczynając od celów biznesowych. Generują one wymagania, które bę- dziemy musieli określić nieformalnie. W tym rozdziale przyjrzymy się częściowym im- plementacjom tych nieformalnych wymagań przy użyciu mikrousług. 2.2.1. Cele biznesowe Gazeta oferuje zarówno darmowe, jak i płatne treści. Aby wyświetlić płatne treści, użytkownicy muszą dokonać płatnej subskrypcji. Przychody gazety są generowane przez subskrypcje i reklamy. Reklama może być kierowana do konkretnego użytkowni- ka lub skupiać się na odpowiedniej treści, aby być bardziej skuteczna. Aby zwiększyć przychody z reklam, czas korzystania z witryny przez użytkowników powinien być zmaksymalizowany. Osoby pracujące nad gazetą, korzystające z witryny, powinny mieć możliwość publi- kowania artykułów w sposób ciągły za pomocą systemu zarządzania treścią. Powinny móc również przeglądać statystyki dotyczące treści, które opublikowały, aby uzyskać informacje zwrotne na temat ich skuteczności. Aby zmaksymalizować dostęp do gazety, jest ona dostarczana za pośrednictwem strony internetowej i aplikacji mobilnych. Powinna być również dostarczona wyszu- kiwarka do przeszukiwania treści artykułów darmowych i płatnych, zoptymalizowana pod kątem uzyskania jak największej trafności. 2.2.2. Wymagania nieformalne Na podstawie celów biznesowych możesz przedstawić listę nieformalnych wymagań. Wymagania będą wpływać na Twoje decyzje wdrożeniowe: 6 Mikrousługi są tematem wartym całej książki — wybiegają daleko poza ramy szablonowej definicji. Zaraz, zaraz… Kup książkęPoleć książkę 2.2. Studium przypadku: wydanie cyfrowe gazety 63  Treść składa się z artykułów, z których każdy ma osobną stronę.  Istnieją również specjalne strony z listami artykułów, takie jak strona tytułowa, a także strony pod kątem zainteresowań.  Witryna internetowa oraz aplikacja we wszystkich wersjach powinny korzystać z opartego na REST wspólnego API, obsługiwanego przez część serwerową systemu.  System powinien dostarczać statyczne wersje treści podstawowych, aby wyszukiwarki internetowe mogły je zindeksować, ale może również dostarczać dynamicznie tworzoną zawartość dodatkową.  System musi implementować koncepcję użytkowników, zarówno czytelników, jak i autorów, z odpowiednimi uprawnieniami dla różnych poziomów dostępu.  Treści na stronach należy kierować do bieżącego użytkownika, dopasowując zawartość do jego profilu za pomocą reguł biznesowych lub algorytmów optymalizacyjnych.  Witryna jest ciągle rozwijana, podlega ostrej konkurencji z innymi internetowymi gazetami, więc nowe funkcjonalności muszą być dodawane szybko. Zmiany te obejmują specjalne krótkoterminowe miniaplikacje, takie jak przekazujące interaktywne treści podczas wyborów. 2.2.3. Podział funkcjonalny Z czysto funkcjonalnej perspektywy i bez odniesienia do żadnej architektury można stwierdzić, że wspomniane wymagania już teraz pozwalają zastanowić się nad tym, jak wdrożyć system gazety. Oto kilka rzeczy, które ten system powinien wykonywać:  obsługa zawartości artykułów oraz operacje odczytu, zapisu i zapytań;  tworzenie zawartości strony i dostarczanie pamięci podręcznej używanej do skalowania;  obsługa kont użytkowników: logowanie, wylogowanie, profile itd.;  dostarczanie ukierunkowanych treści i mapowanie tożsamości użytkowników na odpowiednie artykuły. Te funkcjonalności sugerują niektóre komponenty oprogramowania, które powinieneś zbudować. Przez chwilę udajmy, że są one reprezentowane przez klasy zorientowane obiektowo:  ArticleHandler — zapewnia operacje na zawartości artykułu;  PageBuilder — generuje strony;  PageCache — zarządza pamięcią podręczną strony;  UserManager — zarządza użytkownikami;  ContentMapper — decyduje o tym, jakie treści pokazać użytkownikowi. Możesz nawet narysować możliwe zależności między tymi komponentami, tak jak pokazano na rysunku 2.1. Kup książkęPoleć książkę 64 ROZDZIAŁ 2. Usługi Rysunek 2.1. Możliwa architektura komponentów dla systemu gazety internetowej Czy to właściwe komponenty? Czy są to właściwe zależności? Jeszcze za wcześnie, by to stwierdzić. Czy to są mikrousługi? Być może. Architektura mikrousług musi zapewniać proces analityczny decydujący o tym, które mikrousługi zbudować. Jakoś musisz przejść od nieformalnych wymagań do konkretnego zestawu usług w produk- cji. Aby rozpocząć ten proces, przyjrzyjmy się bliżej właściwościom architektur mi- krousług i sposobom ich konstruowania. 2.3. Architektury mikrousług Jeśli przyjmiemy, że mikrousługi powinny porozumiewać się ze sobą za pomocą ko- munikatów, i chcemy, aby były niezależne, oznacza to, że muszą mieć dobrze zdefi- niowany interfejs komunikacyjny. Odrębne komunikaty są najbardziej naturalnym mechanizmem do definiowania tego interfejsu7. Zrozumienie, że komunikacja między usługami może być określona w kategoriach komunikatów, pozwala jeszcze lepiej uświadomić sobie dynamiczną naturę mikro- usług. Na jednym poziomie abstrakcji musisz zrozumieć, które usługi komunikują się ze sobą. W praktyce wiedza ta jest mniej użyteczna, niż mogłoby się wydawać. Wraz ze wzrostem liczby usług rośnie również liczba połączeń między nimi i pełna sieć inte- rakcji staje się trudna do wizualizacji. Jednym ze sposobów na złagodzenie tej złożo- ności jest przyjęcie podejścia opisania systemu od strony poszczególnych komunika- tów. Zauważmy, że usługi i komunikaty to dwa aspekty tej samej struktury. Często lepiej jest patrzeć na system mikrousług od strony komunikatów, które przechodzą przez ten system, a nie od strony usług, które przetwarzają odbierane komunikaty. Z tej perspektywy można analizować sposoby interakcji, znajdować typowe wzorce i two- rzyć projekt architektury mikrousług. 7 Nie wyklucza to innych mechanizmów komunikacyjnych, takich jak transmisja strumieniowa danych, ale są one zazwyczaj używane do specjalnych zastosowań lub jako warstwa transportowa dla osadzonych wiadomości. Kup książkęPoleć książkę 2.3. Architektury mikrousług 65 2.3.1. Architektura miniserwerów webowych W architekturze miniserwerów webowych mikrousługi to nic innego jak serwery webowe, które oferują niewielkie interfejsy oparte na REST. Komunikaty to żądania i odpowiedzi HTTP. Treść komunikatu to dokumenty JSON lub XML albo proste zapytania. Jest to architektura synchroniczna. Żądania HTTP wymagają odpowiedzi. Przyjmiemy to jako punkt wyjściowy, a następnie zastanowimy się, jak sprawić, by te miniserwery były bardziej podobne do komponentów oprogramowania. Każda mikrousługa musi znać lokalizację innych usług, z którymi chce się komu- nikować. Jest to jednocześnie i ważna cecha, i słabość miniserwerów webowych. Kiedy jest to tylko kilka usług, możesz skonfigurować ręcznie połączenia między nimi, ale szybko staje się to niemożliwe do zarządzania, kiedy liczba usług rośnie. Standar- dowym rozwiązaniem jest mechanizm wykrywania usług. Aby zapewnić wykrywanie wszystkich usług, musisz uruchomić odpowiednią usługę w swoim systemie, która przechowuje listę wszystkich mikrousług i ich lokalizacji w sieci. Każda mikrousługa musi przesłać zapytanie do usługi wykrywania, aby znaleźć inne usługi, z którymi chce się komunikować. Niestety to rozwiązanie ma dużo ukrytej złożoności. Po pierwsze, utrzymywanie usługi wykrywania, która przechowuje infor- macje zgodne z rzeczywistością, jest nietrywialne — napisanie dobrej implementacji wykrywania jest trudne8. Po drugie, mikrousługi muszą przechowywać wiedzę o in- nych usługach, którą uzyskają od usługi wykrywania, i muszą radzić sobie z problemem sprawdzania poprawności tej wiedzy. Po trzecie, przechowywanie tych informacji prowadzi do ścisłej zależności między usługami. Dlaczego? Rozważ to, że wewnątrz kodu monolitycznego potrzebne jest odwołanie do obiektu w celu wywołania jego me- tody. Teraz robisz to samo, tylko że poprzez sieć — potrzebujesz lokalizacji sieciowej i punktu końcowego adresu URL. Jeśli używasz wykrywania usług, wprowadzasz potrzebę dostarczenia dodatkowego kodu i modułów do swoich usług, by współpra- cowały z mechanizmem wykrywania. W najprostszej konfiguracji ta architektura jest typu punkt-punkt. Mikrousługi ko- munikują się ze sobą bezpośrednio. Możesz rozszerzyć tę architekturę dzięki bardziej elastycznym wzorcom komunikatów poprzez używanie inteligentnego równoważenia obciążenia. Aby skalować daną mikrousługę, umieść moduł równoważenia obciążenia protokołu HTTP9 tak, aby obsługiwał ruch dla zbioru instancji mikrousług. Będziesz potrzebował tego dla każdej mikrousługi, którą chcesz skalować. Zwiększy to złożoność Twojego wdrożenia, ponieważ musisz również zarządzać konfiguracjami modułu rów- noważenia obciążenia, tak samo jak swoimi mikrousługami. 8 Dostępne są względnie wydajne implementacje wykrywania usług: ZooKeeper (https://zookeeper. apache.org/), Consul (https://consul.io/), etcd (https://github.com/coreos/etcd) i inne. Żadna z nich nie jest w pełni zgodna z wymaganiami w kwestii odporności na błędy i sprawdzania spójności danych, mimo że wszystkie są przygotowane do pracy w środowiskach produkcyjnych. Sprawdź artykuły z serii „Jepsen” autorstwa Kyle’a Kingsbury’ego na https://aphyr.com/tags/jepsen, gdzie znajduje się szczegółowa analiza. 9 Odpowiednie komponenty równoważenia obciążenia to NGINX (http://nginx.org/), HAProxy (http://www.haproxy.org/) i Eureka (https://github.com/Netflix/eureka). Kup książkęPoleć książkę 66 ROZDZIAŁ 2. Usługi Jeśli sprawisz, że Twój moduł równoważenia obciążenia będzie inteligentny, bę- dziesz mógł zacząć czerpać większe korzyści z mikrousług. Nic na to nie wskazuje, że wszystkie mikrousługi zarządzane przez dany moduł muszą mieć tę samą wersję tej samej mikrousługi. Możesz częściowo wdrożyć i przetestować nowe wersje mikrousługi w środowisku produkcyjnym, dodając je do danej grupy równoważenia obciążenia. Jest to prosty sposób na uruchamianie wielu wersji tej samej mikrousługi w tym sa- mym czasie. Możesz umieścić różne mikrousługi za tym samym modułem równoważenia ob- ciążenia i użyć tego komponentu, aby dopasować do wzorca właściwości przychodzą- cych komunikatów i następnie przypisać je do odpowiedniego typu mikrousługi10. Rozważ moc, jaką Ci to daje — możesz zwiększyć funkcjonalność systemu poprzez dodanie nowej mikrousługi i zaktualizowanie zasad modułu równoważenia obciąże- nia. Nie trzeba zmieniać, aktualizować, ponownie wdrażać ani w żaden inny sposób dotykać innych uruchomionych usług. Zdolność do wykonywania tego rodzaju małych, niewiele znaczących i niskiego ryzyka zmian w systemie produkcyjnym w dużym stop- niu stanowi o atrakcyjności architektury mikrousługi. To sprawia, że ciągłe dostarczanie kodu do systemu produkcyjnego jest dużo bardziej możliwe. Równoważenia obciążenia po stronie klienta Moduł równoważenia obciążenia nie musi być oddzielnym procesem mającym dostęp do nasłuchujących mikrousług. Możesz użyć biblioteki po stronie klienta, osadzonej w mi- krousłudze klienta, aby przeprowadzić inteligentne równoważenie obciążenia. Zaletą tego rozwiązania jest to, że nie musisz martwić się wdrażaniem i konfigurowaniem wielu sys- temów równoważenia obciążenia w sieci. Taki system może korzystać z mechanizmu wykrywania usług, aby określić, gdzie wysłać komunikaty. 2.4. Diagramy mikrousług Narysujmy niektóre z tych konfiguracji, aby ułatwić ich wizualizację. Tradycyjne diagramy sieciowe są mniej przydatne dla mikrousług, ponieważ jest dla nich znacz- nie więcej komponentów i zawsze jesteśmy bardziej zainteresowani przepływem komunikatów niż ich zwykłym istnieniem. Rysunek 2.2 pokazuje prosty system typu punkt-punkt: część strony gazety. Później zbudujemy pełną strukturę, ale skupmy się najpierw na interakcjach między mikrousługami budującymi stronę artykułu. 10 Jednym ze sposobów, aby to zrealizować, jest użycie modułów rozszerzeń dla serwerów takich jak NGINX. Możesz również rozwinąć własne rozwiązanie, używając platformy np. Node.js (https://nodejs.org/). Rysunek 2.2. Budowanie strony artykułu Kup książkęPoleć książkę 2.5. Drzewo zależności mikrousług 67 Usługa artykuł przechowuje dane artykułu. Usługa strona-z-artykułem tworzy kod HTML dla danego artykułu. Każdy artykuł ma własny unikatowy adres URL strony. Inteligentny system równoważenia obciążenia tworzy trasę dla żądań adresu URL artykułu pochodzących od klientów przeglądarek internetowych do usługi strona-z- artykułem. Przyjmijmy za pewnik, że są to usługi do zbudowania. Widać, że różnią się od bardziej tradycyjnych elementów zorientowanych obiektowo, sugerowanych wcześniej (PageBuilder, ArticleHandler). W odpowiednim czasie zaczniesz tworzyć te usługi na podstawie komunikatów, które definiują system. Teraz zobaczmy, jak konwencje wi- doczne na diagramie mogą pomóc w zademonstrowaniu projektu systemu. Na rysunku 2.2 linie ciągłe reprezentują komunikaty synchroniczne. To oznacza, że usługa klienta oczekuje natychmiastowej odpowiedzi ze strony nasłuchującej usługi, czyli że nie może kontynuować swojej pracy bez tej odpowiedzi. Strzałki są skiero- wane od usługi klienta w stronę usługi nasłuchującego. Strzałki są ciągłe, co oznacza, że usługa nasłuchująca konsumuje komunikat, czyli że nikt inny go nie widzi. Mikrousługi są reprezentowane przez sześciokąty. Elementy zewnętrzne dla sys- temu (np. przeglądarka internetowa) są reprezentowane jako prostokąty, a elementy wewnętrzne w systemie (np. moduł równoważenia obciążenia) — jako koła. W przy- padku mikrousług sześciokąt nie oznacza jednej mikrousługi, ale jedną lub więcej działających instancji mikrousługi tego samego rodzaju. Trzeba o tym pamiętać. W sys- temie produkcyjnym prawie nigdy nie uruchamiasz tylko jednej instancji danej mi- krousługi. 2.5. Drzewo zależności mikrousług Mikrousługi z założenia są zależne od siebie, ponieważ każda wykonuje tylko nie- wielką część pracy dla dowolnego żądania HTTP lub dla innego zadania w systemie. W synchronicznej architekturze typu punkt-punkt, którą moglibyśmy nazwać mikro- usługami podstawowymi, drzewo zależności może być trudne do zarządzania w miarę wzrostu. Pułapka rozproszonego monolitu Rozproszony monolit jest nieprzyjemną pułapką czekającą na początkujących twórców mikrousług, którzy naiwnie wykorzystują tradycyjne wzorce obiektowe w kontekście mikrousług. W głównym nurcie języków zorientowanych obiektowo należy podać sygna- tury dokładnej metody i typu obiektu. Jeśli typy nie będą zgodne, pojawi się błąd kom- pilacji. (Czy to stanowi prawdziwą korzyść, jeśli chodzi o tworzenie oprogramowania, czy też nie, to już temat dyskusji na inną okoliczność). W architekturze mikrousług niedopasowanie typu nie jest błędem kompilacji, ale błędem czasu wykonywania, który może położyć Twój system. Używanie typów ści- słych oznacza, że budujesz rozproszony monolit, w którym wywołania metod są uru- chamiane w sieci. O wiele łatwiej jest zbudować tradycyjny monolit! Aby zyskać korzyści z architektury mikrousług, musisz zostawić niektóre z najlepszych praktyk pochodzących ze świata mo- nolitycznego. Kup książkęPoleć książkę 68 ROZDZIAŁ 2. Usługi Głównym zagrożeniem są zwłaszcza zależności usług, w których jedna mikrousłu- ga lub ich większa liczba staje się współzależna, zatem nowe wersje muszą być wdro- żone w tym samym czasie. To szczególnie łatwo może nastąpić, jeśli używasz bibliotek serializacji obiektów, które wymagają pełnej zgodności wszystkich właściwości znaj- dujących się w komunikatach JSON lub XML. Dodaj pole do encji w jednej mikro- usłudze, a będziesz musiał je dodać do wszystkich mikrousług, które używają tej jed- nostki. I zanim się obejrzysz, skończysz z rozproszonym monolitem — najgorszym z obu światów. Wróćmy do studium przypadku. Wyświetlanie artykułu w gazecie wymaga wyko- nania większej liczby czynności niż pobieranie danych artykułu i jego formatowanie. Niektóre z tych działań pokazano na rysunku 2.3. Prawdopodobnie masz do czynienia z aktywnie zalogowanym użytkownikiem; musisz wyświetlić jego status w polu u góry strony, gdzie użytkownik może się wylogować lub wybrać zarządzanie swoim kontem. To sugeruje wybranie mikrousługi z odpowiedzialnością za użytkowników. Będziesz miał do czynienia z usługą reklamową, ponieważ to część biznesowego modelu dla gazety. Rysunek 2.3. Budowanie strony artykułu z całkowitą zawartością Usługa strona-z-artykułem pobiera treść z usług: reklama, użytkownik i artykuł. Nie ma sensu przesyłać żądań po kolei, czekając na pomyślną odpowiedź z poprzedniego, zanim zostanie wysłane następne. Zamiast tego musisz wysłać wszystkie żądania w tym samym czasie i odebrać odpowiedzi, gdy tylko przyjdą. Zaimplementowanie tego nie jest wielką filozofią, ale na pewno trudniej jest wtedy utrzymać porządek w kodzie. Musisz rozwinąć pewne abstrakcje związane z wysyłaniem i odbieraniem komunikatów, aby można było ujednolicić warstwę komunikacji między usługami. Kup książkęPoleć książkę 2.5. Drzewo zależności mikrousług 69 Na rysunku 2.3 możesz zobaczyć, że baza danych jest eksponowana przez usługę artykuł. Nigdy nie pokazuj swoich decyzji implementacyjnych innym usługom! To w zasadzie złota reguła. Jedną z największych korzyści, które powinieneś uzyskać w za- mian za dodatkową złożoność zarządzania mikrousługami, jest to, że w systemie pro- dukcyjnym będziesz miał możliwość zmiany niemal wszystkiego niezależnie od innych elementów. Powinieneś być w stanie zmienić bazę danych prawie bez konieczności ponownego uruchamiania usługi strona-z-artykułem. Dzięki usłudze strona-z-artykułem możesz policzyć, ile razy artykuł był czytany, ale obarczenie wspominanej usługi tą funkcją nie jest dobrym pomysłem. Mogą być jeszcze inne rzeczy wykonywane przez różne usługi, które to rzeczy chciałbyś zrobić, gdy artykuł jest czytany (np. optymalizacja silnika rekomendacji). Jednym ze sposobów odłączenia tych funkcjonalności od usługi strona-z-artykułem jest użycie asynchro- nicznego komunikatu, oznaczonego kropkowaną linią na rysunku 2.4. Usługa strona- -z-artykułem wysyła komunikat, który zawiera informację o zdarzeniu, że artykuł zo- stał przeczytany, ale usługi tej „nie obchodzi”, ile osób otrzymało tę odpowiedź lub ile osób może jej potrzebować. Rysunek 2.4. Informowanie innych usług o tym, że artykuł został przeczytany W tym przypadku usługi analityka i rekomendacja nie konsumują odbieranych ko- munikatów. Te komunikaty są zamiast tego monitorowane, jak na to wskazują otwarte groty strzałek. Aby to osiągnąć, możesz użyć kolejki przechowującej zduplikowane komunikaty11. Istotne jest myślenie na właściwym poziomie architektonicznym. Liczy 11 Jednym z wielu sposobów osiągnięcia tego jest użycie funkcjonalności publikowania/ subskrybowania brokera Redis: https://redis.io/commands/pubsub. Kup książkęPoleć książkę 70 ROZDZIAŁ 2. Usługi się przede wszystkim nie sposób implementacji takiej interakcji z komunikatami, ale fakt, że są to komunikaty asynchroniczne i monitorowane. „Nie powtarzaj się” nie jest złotą regułą Mikrousługi pozwalają bezpiecznie naruszać zasadę „nie powtarzaj się” (ang. DRY — don’t repeat yourself). W tradycyjnym projektowaniu oprogramowania zaleca się ge- neralizację powtarzających się bloków kodów, aby nie skończyć na utrzymywaniu wielu kopii nieznacznie różniącego się kodu. Projektowanie mikrousług polega na czymś do- kładnie odwrotnym: każda mikrousługa może iść własną drogą. Antywzorcem jest tutaj szukanie wspólnej logiki biznesowej (infrastruktura jest, jak zawsze, wyjątkiem) i próba napisania jak najbardziej ogólnych modułów do wykorzystania w wielu mikrousłu- gach. Dlaczego? Ponieważ ogólny kod jest złożony, musi zajmować się przypadkami wy- jątkowymi i jest główną przyczyną narastającego długu technicznego. Ogólne reguły biznesowe oraz modele domen stają się z czasem skomplikowane, ponieważ ogólny przypadek nie jest wystarczający, aby poradzić sobie ze złożonością realnego świata. Lepiej zachować wszystko oddzielnie, na prostszych zasadach specy- ficznych dla danego przypadku i na małych modelach odpowiadających poszczególnym mikrousługom. Dzięki temu Twoje mikrousługi będą niezależne i pozwolą programistom pracować równolegle na prostszych fragmentach kodu. Wraz z rozwojem systemu rośnie również drzewo zależności między usługami za- równo wszerz, jak i wzdłuż. Na szczęście doświadczenia w tej dziedzinie sugerują12, że wszerz rośnie szybciej niż wzdłuż. Gdy drzewo w końcu się rozrasta, zaczynają się pojawiać problemy związane z opóźnieniem przetwarzania komunikatów. Oto sedno problemu: czas reakcji w sieci ulega wypaczeniu, kiedy większość odpowiedzi wraca szybko, ale niektóre wymagają dużo więcej czasu niż przeciętnie. Dlatego aby wyzna- czać cele wydajnościowe, używamy percentyli13, ponieważ średnia nie ma charakteru informacyjnego. Gdy wiele elementów komunikuje się w krótkim okresie, czasy reakcji najgorszych przypadków rosną znacznie szybciej niż przeciętnych i niska wydajność w niewielkiej liczbie przypadków staje się w efekcie przestojem i następuje przekroczenie limitów czasu. Jak sobie radzisz z tym problemem? Jednym ze sposobów jest scalanie usług14, aby zmniejszyć zapotrzebowanie ruchu sieciowego. To jest poprawna optymalizacja wydajności, szczególnie w dojrzałych systemach. Znacznie mniej boli upewnianie się, że Twój kod infrastruktury jest w dobrej kondycji i że prace związane z tworze- niem sieci i usługą wyszukiwania są wyabstrahowane względem głównej logiki biz- nesowej mikrousług. 12 Cenną inwestycją w zrozumienie architektury mikrousługi jest obejrzenie konferencji wideo, których wiele jest dostępnych w internecie. Omówiono w nich takie kwestie z praktycznego punktu widzenia w działających systemach produkcyjnych. 13 Percentyl pokazuje, jaki procent odpowiedzi pojawił się w danym czasie. Na przykład percentyl 90 — 500 ms czasu reakcji oznacza, że 90 odpowiedzi trwało krócej niż 500 ms. 14 Scalanie usług to w 100 akceptowalna optymalizacja wydajności i tylko wydajności. Niemniej tracisz wtedy wiele korzyści z architektury mikrousługi. Wytyczna, by tworzenie mikrousługi zajmowało co najwyżej iterację, to także tylko wytyczna. Ale otrzymujesz wynagrodzenie za wydanie swojego zawodowego osądu w tych sprawach. Kup książkęPoleć książkę 2.5. Drzewo zależności mikrousług 71 2.5.1. Architektura komunikatów asynchronicznych Jako kompletną alternatywę względem podejścia typu punkt-punkt może warto przetransportować wszystkie Twoje komunikaty za pośrednictwem kolejki komuni- katów? W tej architekturze masz jedną lub więcej kolejek, które obsługują wszystkie komunikaty. Usługi klienckie publikują komunikaty w kolejce, a usługi odsłuchowe je odczytują. Korzystanie z kolejki komunikatów zapewnia większą elastyczność za cenę zwięk- szonej złożoności systemu. Kolejka taka jest kolejnym punktem, gdzie mogą wystąpić awarie, i wymaga takiej samej dbałości i uwagi jak baza danych w systemie produk- cyjnym. Ponadto, w ramach skalowania systemu, kolejki komunikatów muszą być dystrybuowane podobnie jak bazy danych. Musisz zdecydować, jak przekierowywać komunikaty. Z kolejką Twoje usługi przy- najmniej nie muszą znać lokalizacji w sieci innych usług. Nadal jednak muszą wie- dzieć, jak znaleźć kolejkę. Musisz używać tzw. tematów komunikatów, aby odpowiednio przekierowywać przychodzące komunikaty, i Twoje usługi także muszą o nich wie- dzieć. Zrozum lepiej to podejście, przyglądając się pewnej strategii: Rozpraszanie- -Zbieranie. Większość rodzajów treści jest przydatna nawet wtedy, gdy nie są kompletne lub całkowicie poprawne. W przykładzie z internetową gazetą pokazywanie nieaktualnej wersji artykułu pobranej z pamięci podręcznej jest zdecydowanie lepsze z perspek- tywy biznesowej niż wyświetlanie błędu strony, jeśli usługa artykuł akurat działa niepoprawnie. Liderzy większości organizacji wolą utrzymywać swój biznes otwarty, nawet jeśli nie mogą zaoferować pełnej usługi15. To jest po prostu sprawa zdroworoz- sądkowego biznesu. Firmy chcą być dostępne dla swoich klientów, nawet jeśli ich produkty nie są spójne. Co więcej, klienci również mają takie preferencje — kanapka z szynką i serem z serwisu hotelowego, kiedy przyleciałeś o 2 nad ranem, jest lepsza niż brak jedzenia! Rozważmy asynchroniczne podejście do budowania strony artykułu. Taka strona składa się z wielu elementów: statusu użytkownika, reklam, tekstu i metadanych ar- tykułu, miniprofilu autora, linków z powiązanymi treściami itd. Strona jest nadal przydatna, nawet jeśli większość tych elementów się na niej nie pojawia. Wskazuje to na rozpraszanie komunikatów w mikrousługach odpowiedzialnych za generowanie za- wartości, a następnie asynchroniczne zbieranie odpowiedzi przed upływem wyznaczo- nego czasu. Każda usługa dostaje, powiedzmy, 200 ms na odpowiedź. Jeśli nie wyrobi się w tym czasie, jej element nie jest wyświetlany, ale przynajmniej użytkownik coś otrzymuje. Ta technika ma także tę zaletę, że użytkownik ma odczucie, że Twoja strona działa znacznie szybciej, ponieważ dostarczanie stron nie jest spowalniane przez wolne usługi. 15 Czy banki odmawiają przetwarzania płatności, gdy nie mogą dokonywać transakcji typu ACID? Czy kiedykolwiek przekroczyłeś swój dopuszczalny debet? Banki rozwiązują ten problem poprzez reguły biznesowe (opłaty karne), a nie reguły informatyczne, które mogłyby zaszkodzić ich działalności. Kup książkęPoleć książkę 72 ROZDZIAŁ 2. Usługi Na rysunku 2.5 usługa strona-z-artykułem wysyła komunikat asynchroniczny. Usługi artykuł, reklama i użytkownik monitorują, ale nie konsumują tego komunikatu. Robią swoje i generują odpowiedzi. Ich odpowiedzi są również asynchroniczne. Usługa strona-z-artykułem konsumuje te odpowiedzi, co jest wskazane przez wypełnio- ną strzałkę. Strzałka ta jest przesunięta względem środka sześciokąta reprezentują- cego usługę strona-z-artykułem, aby wskazać, że usługa ta jest źródłem tego przepływu komunikatu. Ten wzór jest powszechny; schemat „streszcza” rozpraszanie i zbieranie jedną przerywaną linią. Pamiętaj, że te elementy nie są indywidualnymi przypadkami usług, ale raczej reprezentują wiele instancji16. Rysunek 2.5. Wzorzec Rozpraszanie-Zbieranie Kolejka komunikatów powoduje, że łatwiej jest zaimplementować strategię Rozpra- szanie-Zbieranie i w ogóle znacznie bardziej pasuje ona do asynchronicznych wzor- ców. W praktyce tworzysz temat żądania dla usługi strona-z-artykułem, gdzie wsta- wiane są komunikaty-żądania, a także temat odpowiedzi dla usług dostarczających treść, by mogły tam wstawiać komunikaty-odpowiedzi. Musisz również zidentyfiko- wać i odpowiednio oznaczyć komunikaty, aby mogły zostać zignorowane przez usłu- gi, które nie są nimi zainteresowane. Ale ostrożnie, jest wiele różnorodnych trybów awarii kolejek komunikatów. W rozdziale 3. bardziej szczegółowo zbadamy wzorce ko- munikatów i ich tryby awarii. Czym kierują się ludzie przy wyborze w systemie produkcyjnym między strategią synchroniczną a asynchroniczną? Prawie wszystkie systemy produkcyjne są hybrydami. Asynchroniczne kolejki komunikatów mają większą tolerancję na błędy i umożliwiają łatwiejszą dystrybucję zadań. Dodawanie nowych usług jest łatwe i nie musisz się zbytnio martwić mechanizmem wykrywania usług. Z drugiej strony synchroniczna ko- munikacja typu punkt-punkt to absolutna konieczność, kiedy zależy Ci na niewielkim opóźnieniu. Również w początkowym stadium projektu znacznie szybciej można rozpo- cząć, używając komunikacji punkt-punkt. 16 Netflix, główny zwolennik mikrousług, zwykle jest wdrażany w jednostkach grupy Amazon Web Services Auto Scaling. Nie ma tu mowy o myśleniu w kategoriach pojedynczych maszyn lub kontenerów. Kup książkęPoleć książkę 2.6. Projekty monolityczne a projekty mikrousługowe 73 2.6. Projekty monolityczne a projekty mikrousługowe Monolityczna architektura oprogramowania powoduje negatywne konsekwencje, które w opinii wielu są podstawowymi wyzwaniami dotyczącymi całego rozwoju oprogra- mowania. Po bliższym, krytycznym zbadaniu to założenie można postawić na głowie. Wiele wyzwań i wiele rzekomych rozwiązań tych wyzwań wynika bezpośrednio z in- żynierskich wpływów architektury monolitycznej i staje się dyskusyjnych przy innym inżynierskim podejściu. Istnieją trzy konsekwencje monolitów. Pierwsza jest taka, że wszyscy członkowie zespołu programistów muszą starannie koordynować swoje działania w taki sposób, aby nawzajem się nie blokować. Jest jeden kod bazowy, więc jeśli pojedynczy pro- gramista zepsuje kompilację, to wszyscy deweloperzy zostaną zablokowani. Kod na- turalnie zmierza w kierunku głębokiej, wielowymiarowej zależności. Jest to konsekwen- cja postrzegania najlepszych praktyk. Refaktoryzacja wspólnego kodu do bibliotek współdzielonych tworzy głębokie drzewa zależności. Wymagana liczba poprawek, kiedy zmieniana jest struktura kodu, jest wykładniczo proporcjonalna do głębokości tej struktury w drzewie zależności. Zespoły często podejmują racjonalny wybór, by zapakować złożoność w coraz większą liczbę warstw, próbując ją ukryć i opanować. Monolity znacznie zwiększają koszty pracy równoległej i tym samym spowalniają rozwój oprogramowania. Drugą konsekwencją monolitów jest szybkie uzyskanie długu technicznego. Nie ma naturalnej siły ograniczającej. Dobrze skonstruowany, prawidłowo rozłączny, czysty, zorientowany obiektowo początkowy projekt jest zbyt słaby, aby oprzeć się natychmiastowym potrzebom całego zespołu pracującego pod presją czasu, który to zespół chce jak najszybciej dostarczyć bieżące funkcjonalności. Jest zbyt wiele sposo- bów, by jeden fragment kodu mógł wpłynąć na inny fragment — zbyt wiele sposobów na tworzenie zależności. Pierwszym przykładem jest korozja struktury danych. Biorąc pod uwagę wstępną definicję wymagań, starsi programiści i architekci projektują odpowiednie struktury danych, by opisać istotę problemu. Są to wspólne struktury danych i muszą być do- stosowane do wszystkich znanych wymagań oraz przewidywać przyszłe wymagania, więc mają tendencję do większej złożoności. Głębokie zagnieżdżenie odniesień mię- dzy strukturami jest znakiem ostrzegawczym przed próbą bycia ponadczasowym. Niestety świat często potrafi przechytrzyć naszą skromną inteligencję, a struktury da- nych nie mogą sprostać rzeczywistym potrzebom biznesowym w miarę ich pojawiania się. Zespół jest zmuszony do wprowadzania prowizorki, niejawnych konwencji i two- rzenia rozszerzeń ad hoc17. Później nowi członkowie zespołu oraz młodsi programiści, nie rozumiejąc sił rzą- dzących strukturami danych, mogą wprowadzać subtelne i podstępne błędy, które powodują, że cały zespół musi poświęcić nieproporcjonalnie dużo czasu na poprawki 17 Deklaratywne struktury są zwykle najlepszą opcją do odzwierciedlania świata, ponieważ można nimi manipulować w powtarzalny, spójny, umyślnie ograniczony sposób. Jeśli wprowadzisz sposoby osadzania kodu wykonywalnego do obsługi specjalnych przypadków takich jak „darmowa karta wyjścia z więzienia”, sprawy mogą się szybko skomplikować i skończysz w więzieniu dłużników technicznych. Kup książkęPoleć książkę 74 ROZDZIAŁ 2. Usługi i rozwiązania poprawiające wydajność18. Ostatecznie zespół musi podjąć szeroko za- krojone działania związane z refaktoryzacją, aby odzyskać pewną miarę prędkości programowania. Globalnie udostępnione struktury danych i modele są tak samo złe jak zmienne globalne i nie mają naturalnej obrony przed technicznym długiem. Trzecią konsekwencją monolitów jest to, że istnieją tylko wdrożenia typu „wszystko albo nic”. Masz starą wersję monolitu uruchomionego w produkcji oraz nową wersję gotową do wdrożenia. Jeżeli chcesz zaktualizować system produkcyjny bez wpływu na działalność biznesową, czeka Cię bardzo stresujący weekend. Być może jesteś bardziej wyrafinowany i stosujesz wdrożenia metodą blue-green, aby zmniejszyć ryzyko19. Nadal musisz zużywać energię na budowanie infrastruktury blue-green i wciąż niewiele Ci to pomoże, jeśli musisz przeprowadzić migracje sche- matu bazy danych, ponieważ niełatwo jest przywrócić poprzednią wersję bazy. Podstawowym problemem jest to, że każda zmiana w systemie produkcyjnym wy- maga przeniesienia całego kodu bazowego. Istnieje duże ryzyko niepowodzenia wdro- żenia na wszystkich poziomach systemu. Brak wystarczającej ilości testów jednostko- wych, akceptacyjnych, integracyjnych, instrukcji testowania oraz możliwości testowania wersji próbnych w systemie produkcyjnym pozwala się zorientować, jak duże jest prawdopodobieństwo niepowodzenia wdrożenia. Przyczyny awarii są często bezpo- średnimi konsekwencjami warunków produkcyjnych, których nie da się zasymulo- wać. Wystarczy, że dane produkcyjne (do których możesz nawet nie mieć dostępu z powodu zasad zachowania poufności informacji) posiadają tylko jeden nieprzewi- dziany aspekt, a już będzie to powodować krytyczne awarie. Trudno jest zweryfiko- wać wydajność przy użyciu danych testowych — dane produkcyjne mogą być nawet kilka rządów wielkości większe. Użytkownicy mogą zachowywać się w nieprzewidy- walny sposób, szczególnie podczas korzystania z nowych funkcjonalności. Może to do- prowadzić do awarii systemu, ponieważ zespół nie był w stanie sobie wyobrazić takich przypadków użycia. Ryzyko związane z wdrożeniami w systemach monolitycznych powoduje powolne, rzadkie publikowanie nowych funkcjonalności, co powstrzymuje przed szybkim wprowadzaniem zmian. Wyzwania inżynieryjne, bo takimi właśnie są, nie mogą zostać rozwiązane przez dowolne podejście do zarządzania projektami. Dotyczą innego zakresu problemów. A jednak niemal powszechnie i wyłącznie firmy próbują je rozwiązać metodami roz- woju oprogramowania i technikami zarządzania projektem. Zamiast cofnąć się o krok i szukać prawdziwego powodu, dla którego projekty są realizowane z opóźnieniem i prze- 18 Pouczający przykład od byłego klienta: klient dodał kolumnę w bazie danych dla treści XML, aby móc przechowywać niewielkie ilości nieustrukturyzowanych danych. Schemat dla tego XML-a zawierał szereg elementów, które można było powtórzyć do przechowywania list. Te listy były nieograniczone. Źródłem problemu było to, że niewielka liczba użytkowników generowała bardzo długie listy, co prowadziło do przechowywania dokumentów XML o ogromnej zawartości. To z kolei wywoływało dziwne i niesamowite błędy w procesie odśmiecania pamięci, których przez długi czas nie można było powiązać z główną przyczyną. 19 Strategia blue-green oznacza, że przez cały czas są produkowane dwie wersje systemu: niebieska i zielona. Tylko jedna z nich jest aktualnie działającym systemem. Aby wdrożyć nową wersję, uaktualnij ją na partycji, która jest offline, a następnie uruchom ją, wyłączając aktualnie działającą. Kup książkęPoleć książkę 2.6. Projekty monolityczne a projekty mikrousługowe 75 kraczają budżet, osoby odpowiedzialne za rozwój oprogramowania raczej obwiniają się za złe wykonanie. A przecież żadne dobre wykonanie nie pozwoli Ci wybudować drapaczy chmur, jeśli założenia są bzdurne20. Rozwiązanie leży gdzieś indziej. Architektura mikrousług jako podejście inżynierskie pozwala nam, twórcom opro- gramowania, ponownie zapoznać się z naszymi najlepszymi praktykami i zapytać, czy naprawdę mogą one sprawić, by dostarczanie nowych funkcjonalności było szybsze i bardziej przewidywalne. Czy może są one jedynie kiepskim sposobem na złagodzenie fundamentalnych problemów rozwoju monolitycznego? Frederick P. Brooks w swojej wydanej w 1975 r. książce Mityczny osobomiesiąc. Eseje o inżynierii oprogramowania szczegółowo wyjaśnia wyzwania związane z rozwojem projektów monolitycznych21. Następnie sugeruje zestaw technik i praktyk nie po to, by rozwiązać problem, ale że- by go ograniczyć i złagodzić. Zasadnicze przesłanie jest takie: brak jakiegokolwiek panaceum — żadne techniki zarządzania projektami nie mogą zapobiec inżynierskim deficytom architektury monolitycznej. 2.6.1. Jak mikrousługi zmieniają zarządzanie projektem Inżynierskie własności architektury mikrousług mają bezpośredni wpływ na wysiłek związany z takim zarządzaniem projektem, by zapewnić jego pomyślną realizację. Jest mniejsze zapotrzebowanie na szczegółowe zarządzanie zadaniami i na wiele bezu- żytecznych ceremonii o charakterze czysto metodycznym22. Zarządzanie projektami opartymi na mikrousługach jest dużo lżejsze. Przeanalizujmy teraz implikacje tego podejścia. 2.6.2. Jednolitość ułatwia estymację Mikrousługi są małe i dobrą praktyką jest ograniczanie ich co najwyżej do jednej ite- racji pracy jednego dewelopera. Szacowanie z punktu widzenia mikrousług jest więc znacznie łatwiejsze niż ogólne szacowanie nakładu pracy na tworzenie oprogramowania, ponieważ musisz wtedy podzielić pracę na kawałki wielkości jednej iteracji. To ważna obserwacja. Tradycyjne systemy monolityczne składają się z heterogenicznych komponentów o różnych rozmiarach i różnej złożoności. Dokładne oszacowanie jest niezwykle trudne, ponieważ każdy element jest szczególnym przypadkiem i ma wie- loaspektowy zestaw interakcji z innymi komponentami poprzez wywołania metod, 20 Od czasów neolitu używano konstrukcji wikliniarsko-glinianych — jest to doskonała technika budowlana, dzięki czemu można zbudować do trzech lub czterech małych pięter. Ale to nie pomoże Ci zbudować Empire State Building. 21 Brooks był kierownikiem projektu systemu mainframe IBM System/360 i jako pierwszy zapisał obserwację, że dodawanie kolejnych programistów do projektu, który już jest opóźniony, sprawia, że staje się on jeszcze bardziej opóźniony. 22 Aby oszczędzić sobie zażenowania, żadna metodyka nie zostanie tutaj nazwana. Ale wiesz, kim jesteś. Jeśli istniałoby takie podejście do zarządzania projektem do rozwoju oprogramowania, które pozwalałoby na konsekwentne dostarczanie nowych funkcji w wielu różnych rodzajach zespołów, to już kierowalibyśmy się ku rozwiązaniu. Jednak w tej kwestii nie widzimy oznak znaczących postępów. Kup książkęPoleć książkę 76 ROZDZIAŁ 2. Usługi współdzielone obiekty, struktury danych oraz schematy bazy danych. Rezultatem jest projektowa lista zadań, która dostosowuje się do wymagań architektury systemu23. W przypadku mikrousług limit złożoności jednej iteracji wymusza jednorodność komponentów, co zwiększa dokładność szacowania. W praktyce jeszcze większa do- kładność może zostać osiągnięta przez klasyfikowanie mikrousług na, powiedzmy, trzy poziomy złożoności oraz przez klasyfikowanie programistów na trzy poziomy doświad- czenia i dopasowanie mikrousług do programistów. Na przykład mikrousługa pozio- mu 1. może zostać ukończona przez programistę poziomu 1. w jednej iteracji, pod- czas gdy mikrousługa na poziomie 3. wymaga programisty poziomu 3., by ukończyć ją w takim samym czasie. Takie podejście daje znacznie większą dokładność niż ogólne szacowanie przy użyciu punktów historyjek użytkownika, które nie uwzględ- niają różnic w możliwościach programistów. Projekt oparty na mikrousługach może być dokładnie zaplanowany za pomocą sensownego, znaczącego mapowania mikro- usług na iteracje. Omówimy ten pomysł bardziej szczegółowo w części II tej książki. Dlaczego ocena oprogramowania jest trudna? Dlaczego tak trudno jest oszacować złożoność komponentów większego systemu? Ści- sła zależność, która niezmiennie występuje w architekturach monolitycznych, oznacza, że programowanie w późniejszych etapach projektu jest wykładniczo wolniejsze, ponieważ wstępne szacunki komponentów na późnym etapie są nadmiernie optymistyczne. Ta wykładnicza powolność wynika z faktu matematycznego (znanego też jako prawo Metcalfa), że liczba możliwych połączeń między węzłami w sieci wzrasta proporcjonalnie do kwa- dratu liczby tych węzłów. I jest jeszcze jeden czynnik: ludzka psychika cierpi na wiele uprzedzeń poznaw- czych, np. nie jesteśmy dobrzy w pracy z prawdopodobieństwami. Wiele z tych uprzedzeń może nie pozwalać na dokładne oszacowanie projektu. Oto przykład: zakotwiczenie jest tendencją polegającą na skupianiu się na pierwszej wartości, którą usłyszysz. Ale złożoność komponentów oprogramowania i tym samym czas zakończenia pracy nad nimi podlega tzw. „prawu mocy”: większość zajmuje krótki czas, ale na część potrzeba dużo więcej czasu24. I zakotwiczenie na wstępnych szacunkach wpływa negatywnie na ko- lejne, gdy złożoność systemu rośnie. Największe i najtrudniejsze komponenty są niedoszacowane, ponieważ większość pracy szacunkowej dotyczy małych komponentów. Stary dowcip o tym, że ostatnie 10 harmonogramu zajmuje 90 czasu, ma w sobie sporo prawdy. 2.6.3. Jednorazowy kod tworzy bardziej przyjazne zespoły Kod mikrousługi jest jednorazowy. Dosłownie można go wyrzucić. Dowolna mikro- usługa jest warta jednej iteracji pracy jednego dewelopera. Gdyby mikrousługa była źle napisana, nie spełniałaby wymagań w wybranym języku lub stałaby się niepo- trzebna ze względu na zmienione wymagania, można by ją wycofać bez głębszego za- 23 Trochę ironicznie — oszacowanie Fibonacciego (gdzie tzw. punkty historyjek użytkownika projektu agile muszą być liczbami Fibonacciego: 1, 2, 3, 5, 8, 13, …) jest wystarczającym dowodem na to, że osiągnięto lokalne maksimum w dokładności szacowania systemów monolitycznych. 24 „Prawa mocy” opisują wiele zjawisk, w których małe przyczyny mogą wywoływać ponadprzeciętne skutki, np. czas trwania trzęsienia ziemi, wynagrodzenia kadry kierowniczej i częstotliwość występowania liter w tekście. Kup książkęPoleć książkę 2.6. Projekty monolityczne a projekty mikrousługowe 77 stanowienia. To miałoby zdrowy wpływ na dynamikę zespołu: nikt nie byłby emocjo- nalnie związany ze swoim kodem ani nie robiłby się z tego powodu zaborczy. Przypuśćmy, że Alicja myśli, iż mikrousługa A, napisana przez Roberta kilka iteracji wcześniej w języku Java, będzie dwa razy wydajniejsza w C++. Powinna się pod
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Tao mikrousług. Projektowanie i wdrażanie
Autor:

Opinie na temat publikacji:


Inne popularne pozycje z tej kategorii:


Czytaj również:


Prowadzisz stronę lub blog? Wstaw link do fragmentu tej książki i współpracuj z Cyfroteką: