Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00364 005456 19040129 na godz. na dobę w sumie
Projektowanie systemów rozproszonych. Wzorce i paradygmaty dla skalowalnych, niezawodnych usług - książka
Projektowanie systemów rozproszonych. Wzorce i paradygmaty dla skalowalnych, niezawodnych usług - książka
Autor: Liczba stron: 184
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-283-4738-0 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> techniki programowania
Porównaj ceny (książka, ebook (-35%), audiobook).

Nowoczesne oprogramowanie musi sprostać wyśrubowanym kryteriom: ma cechować się określoną niezawodnością i skalowalnością, a przy tym powinno korzystać z technologii chmury. Naturalnie powinien to być dobrze zaprojektowany system rozproszony. Dziś standardem jest korzystanie z aplikacji na wielu urządzeniach w różnych lokalizacjach. Niestety, mimo powszechności systemów rozproszonych ich projektowanie nader często przypomina coś w rodzaju czarnej magii, dostępnej dla nielicznych wtajemniczonych. W efekcie architektura każdego systemu jest unikatowa.

Ta książka jest praktycznym przewodnikiem dla projektantów systemów rozproszonych. Zaprezentowano tu kolekcję powtarzalnych wzorców oraz zalecanych praktyk programistycznych, dzięki którym rozwijanie niezawodnych systemów rozproszonych stanie się bardziej przystępne i wydajne. Poza podstawowymi wzorcami systemów rozproszonych przedstawiono tu również techniki tworzenia skonteneryzowanych komponentów wielokrotnego użytku. Znalazło się tu także omówienie zagadnień rozwoju kontenerów i orkiestratorów kontenerów, które zasadniczo zmieniły sposób budowania systemów rozproszonych. Książka ta jest lekturą obowiązkową dla każdego projektanta aplikacji, który chce efektywnie budować niezawodne aplikacje rozproszone!

Najważniejsze zagadnienia:

Twórz systemy rozproszone: skalowalne, elastyczne, niezawodne!

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

Darmowy fragment publikacji:

Tytuł oryginału: Designing Distributed Systems: Patterns and Paradigms for Scalable, Reliable Services Tłumaczenie: Lech Lachowski ISBN: 978-83-283-4738-0 © 2018 Helion SA Authorized Polish translation of the English edition of Designing Distributed Systems ISBN 9781491983645 © 2018 Brendan Burns This translation is published and sold by permission of O’Reilly Media, Inc., which owns or controls all rights to publish and sell the same. 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/prsyro 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ść Spis treści Przedmowa ................................................................................................... 9 Krótka historia rozwoju systemów Krótka historia wzorców w rozwoju oprogramowania 1. Wprowadzenie ................................................................................. 13 14 15 15 16 16 17 17 18 Formalizacja programowania algorytmicznego Wzorce programowania obiektowego Rozwój otwartego oprogramowania Stojąc na ramionach gigantów Wspólny język do dyskusji na temat naszych praktyk Współdzielone komponenty do łatwego ponownego Wartość wzorców, praktyk i komponentów wykorzystania Podsumowanie I Wzorce jednowęzłowe 19 20 21 Przykład przyczepy: dodawanie HTTPS do starszej usługi Dynamiczna konfiguracja za pomocą przyczepy Modułowe kontenery aplikacji 2. Wzorzec Przyczepa ............................................................................ 25 26 27 29 30 31 Budowanie prostej usługi PaaS za pomocą przyczepy Część praktyczna: wdrażanie kontenera topz 3 Poleć książkęKup książkę Projektowanie przyczep pod kątem modułowości i ponownego użycia Parametryzacja kontenerów Definiowanie API każdego kontenera Dokumentowanie kontenerów Podsumowanie 32 33 34 35 36 Używanie ambasadora do fragmentowania usługi 3. Wzorzec Ambasador ..........................................................................37 38 Część praktyczna: implementacja pofragmentowanej usługi Redis 40 Używanie ambasadora do pośredniczenia między usługami 42 Używanie ambasadora do eksperymentowania lub rozdzielania żądań 43 44 Część praktyczna: implementacja 10 eksperymentów Monitorowanie 4. Wzorzec Adapter ...............................................................................47 48 Część praktyczna: monitorowanie za pomocą systemu Prometheus 49 50 Rejestrowanie Część praktyczna: normalizowanie różnych formatów rejestrowania za pomocą fluentd Dodawanie monitora poprawności działania Część praktyczna: dodawanie wszechstronnego monitorowania kondycji MySQL II Wzorce serwowania usług 52 53 54 57 Usługi bezstanowe Sondy gotowości dla mechanizmu równoważenia obciążenia Część praktyczna: tworzenie zreplikowanej usługi w Kubernetes 5. Zreplikowane usługi o zrównoważonym obciążeniu ...........................61 61 63 63 65 67 67 68 69 Usługi ze śledzeniem sesji Zreplikowane usługi warstwy aplikacji Wprowadzenie warstwy buforowania Wdrażanie pamięci podręcznej Część praktyczna: wdrażanie warstwy buforowania 4  Spis treści Poleć książkęKup książkę Rozszerzanie warstwy buforowania Ograniczanie przepustowości i obrona przed atakiem DoS Przerywanie połączenia SSL Część praktyczna: wdrażanie serwera nginx i przerywania połączenia SSL Podsumowanie 72 72 73 74 76 6. Usługi pofragmentowane ................................................................. 77 78 Pofragmentowane buforowanie Dlaczego możesz potrzebować pofragmentowanej pamięci podręcznej? Znaczenie pamięci podręcznej dla wydajności systemu Zreplikowane pofragmentowane pamięci podręczne Część praktyczna: wdrożenie ambasadora i systemu memcached dla pofragmentowanej pamięci podręcznej Funkcja fragmentująca Wybór klucza Spójne funkcje haszujące Część praktyczna: budowanie spójnego fragmentującego pośrednika HTTP Pofragmentowane zreplikowane serwowanie usług Systemy fragmentowania na gorąco 79 79 81 82 86 87 89 90 91 91 Wzorzec Rozrzucaj-Zbieraj z węzłem głównym jako dystrybutorem Część praktyczna: rozproszone wyszukiwanie dokumentów 7. Wzorzec Rozrzucaj-Zbieraj ................................................................ 93 94 95 96 97 98 Część praktyczna: pofragmentowane wyszukiwanie dokumentów Wybieranie odpowiedniej liczby liści Rozrzucaj-Zbieraj z fragmentowaniem liści Skalowanie wzorca Rozrzucaj-Zbieraj pod kątem niezawodności i skali obliczeniowej 100 Kiedy FaaS ma sens 8. Funkcje i przetwarzanie oparte na zdarzeniach ............................... 103 104 104 105 Zalety FaaS Wyzwania FaaS Spis treści  5 Poleć książkęKup książkę Potrzeba przetwarzania w tle Potrzeba przechowywania danych w pamięci Koszty ciągłego przetwarzania opartego na żądaniach Wzorce dla usług FaaS Wzorzec Dekorator: transformacja żądań lub odpowiedzi Część praktyczna: ustawianie wartości domyślnych żądania przed jego przetworzeniem Obsługa zdarzeń Część praktyczna: implementowanie uwierzytelniania dwuetapowego Potoki oparte na zdarzeniach Część praktyczna: implementowanie potoku w celu rejestracji nowego użytkownika 106 106 107 107 107 109 110 111 113 114 Czy musisz wybierać węzeł główny? Podstawy wyboru węzła głównego 9. Wybór własności ............................................................................. 117 119 120 122 123 126 127 128 129 Część praktyczna: wdrażanie etcd Implementacja blokad Część praktyczna: implementowanie blokad w etcd Implementowanie własności Część praktyczna: implementowanie dzierżaw w etcd Obsługa jednoczesnej manipulacji danymi III Wzorce przetwarzania wsadowego 133 Ogólny system kolejki roboczej 10. Systemy kolejek roboczych .............................................................. 135 135 136 139 140 Interfejs kontenera źródłowego Interfejs kontenera roboczego Infrastruktura współdzielonej kolejki roboczej Część praktyczna: implementacja generowania miniaturek plików wideo Dynamiczne skalowanie węzłów roboczych Wzorzec Wiele Węzłów Roboczych 143 144 146 6  Spis treści Poleć książkęKup książkę Wzorce przetwarzania opartego na zdarzeniach 11. Przetwarzanie wsadowe oparte na zdarzeniach .............................. 149 150 151 152 153 154 156 Kopiarka Filtr Rozdzielacz Fragmentator Scalanie Część praktyczna: budowanie przepływu opartego na zdarzeniach dla rejestracji nowego użytkownika Infrastruktura „publikuj-subskrybuj” Część praktyczna: wdrażanie Kafki 157 159 159 Łączenie (czyli synchronizacja barierowa) Redukcja 12. Skoordynowane przetwarzanie wsadowe ....................................... 163 163 166 166 167 168 169 Część praktyczna: zliczanie Suma Histogram Część praktyczna: znakowanie obrazów i potok przetwarzania 13. Wniosek: nowy początek? ............................................................... 173 Skorowidz ...................................................................................... 175 Spis treści  7 Poleć książkęKup książkę 8  Spis treści Poleć książkęKup książkę ROZDZIAŁ 2. Wzorzec Przyczepa Pierwszym wzorcem jednowęzłowym jest Przyczepa (ang. sidecar). Przyczepa jest jednowęzłowym wzorcem składającym się z dwóch kontenerów. Pierw- szym z nich jest kontener aplikacji. Zawiera podstawową logikę aplikacji. Bez tego kontenera aplikacja by nie istniała. Poza kontenerem aplikacji mamy również kontener przyczepy. Rolą przyczepy jest rozszerzanie i usprawnianie kontenera aplikacji, często bez jego wiedzy. W najprostszej formie kontener przyczepy może być używany w celu dodania funkcjonalności do kontenera, który byłoby trudno ulepszyć w inny sposób. Kontenery przyczepy są rozpla- nowywane na tej samej maszynie poprzez niepodzielną grupę kontenerów, taką jak obiekt API pod w Kubernetes. Poza rozplanowaniem na tej samej ma- szynie kontener aplikacji i kontener przyczepy współdzielą różne zasoby, w tym części systemu plików, nazwę hosta i sieć oraz wiele innych przestrzeni nazw. Ogólny wygląd wzorca Przyczepa jest pokazany na rysunku 2.1. Rysunek 2.1. Ogólny wzorzec Przyczepa Podsumowanie  25 Poleć książkęKup książkę Przykład przyczepy: dodawanie HTTPS do starszej usługi Rozważmy przykład starszej usługi internetowej. Wiele lat temu, gdy budowa- no aplikację, bezpieczeństwo wewnętrznej sieci nie było dla firmy aż tak istotne, więc aplikacja obsługuje tylko żądania za pośrednictwem nieszyfrowanego protokołu HTTP, a nie HTTPS. Ze względu na ostatnie incydenty naruszenia bezpieczeństwa zarząd nakazał korzystanie z protokołu HTTPS na wszystkich stronach internetowych firmy. Aby dopełnić niedoli zespołu wyznaczonego do zaktualizowania tej konkretnej usługi sieciowej, kod źródłowy aplikacji zo- stał skompilowany za pomocą starej wersji firmowego systemu kompilacji, który nie jest już używany. Konteneryzacja tej aplikacji HTTP jest dość pro- sta: plik binarny może działać w kontenerze z jakąś starszą wersją dystrybucji Linuksa, bazując na nowocześniejszym jądrze uruchamianym przez orkie- strator kontenerów zastosowany przez zespół. Jednak dodanie do tej aplikacji obsługi protokołu HTTPS jest znacznie trudniejsze. Zespół dywagował nad wskrzeszeniem starego systemu kompilacji albo zaimportowaniem kodu źró- dłowego aplikacji do nowego systemu kompilacji, gdy jeden z członków zespołu zasugerował użycie wzorca Przyczepa, aby łatwiej rozwiązać ten problem. Zastosowanie do tej sytuacji wzorca Przyczepa jest proste. Starsza usługa in- ternetowa jest skonfigurowana do działania wyłącznie na adresie localhost (127.0.0.1), co oznacza, że dostęp do niej będą miały tylko te usługi, które współdzielą sieć lokalną z serwerem. Zwykle nie byłby to praktyczny wybór, ponieważ oznaczałby, że nikt nie może uzyskać dostępu do usługi interneto- wej. Jednak poprzez zastosowanie do starszego kontenera wzorca Przyczepa możemy dodać kontener przyczepy w postaci serwera nginx. Ten kontener nginx rezyduje w tej samej sieciowej przestrzeni nazw co starsza aplikacja internetowa, więc może uzyskać dostęp do usługi działającej na adresie localhost. Jednocześnie usługa nginx może na zewnętrznym adresie IP kapsuły i serwera proxy zatrzymać ruch HTTPS skierowany do starszej aplikacji internetowej (zobacz rysunek 2.2). Ponieważ ten nieszyfrowany ruch jest wysyłany tylko za pośrednictwem lokalnego adaptera pętli zwrotnej wewnątrz grupy kontenerów, zespół do spraw zabezpieczeń sieci jest przekonany, że dane są bezpieczne. W ten sposób, używając wzorca Przyczepa, nasz zespół zmodernizował starszą aplikację bez konieczności wymyślania sposobu na odbudowę nowej aplikacji do obsługi protokołu HTTPS. 26  Rozdział 2. Wzorzec Przyczepa Poleć książkęKup książkę Rysunek 2.2. Przyczepa HTTPS Dynamiczna konfiguracja za pomocą przyczepy Zwykłe pośredniczenie w ruchu skierowanym do jakiejś istniejącej aplikacji nie jest jedynym zastosowaniem przyczepy. Innym typowym przykładem jest synchronizacja konfiguracji. Wiele aplikacji wykorzystuje do parametryzacji plik konfiguracyjny. Może to być nieprzetworzony plik tekstowy lub coś bar- dziej strukturalnego, jak XML, JSON lub YAML. Wiele wcześniejszych aplikacji napisano z założeniem, że ten plik jest obecny w systemie plików, a konfigu- racja będzie odczytywana z danej lokalizacji. Jednak w środowisku natywnym dla chmury często dość przydatne jest użycie do aktualizacji konfiguracji in- terfejsu API. Pozwala to na dynamiczne wysyłanie informacji o konfiguracji za pośrednictwem API zamiast ręcznego logowania się do każdego serwera i aktualizowania pliku konfiguracyjnego za pomocą poleceń imperatywnych. Zapotrzebowanie na takie API wynika zarówno z łatwości użycia, jak i moż- liwości dodawania automatyzacji, takiej jak przywracanie poprzednich wersji, co sprawia, że(cid:31)konfigurowanie (oraz rekonfigurowanie) jest bezpieczniejsze i łatwiejsze. Podobnie jak w przypadku protokołu HTTPS, nowe aplikacje można pisać z założeniem, że konfiguracja jest właściwością dynamiczną, która powinna być pozyskiwana za pomocą interfejsu API chmury, ale dostosowanie i aktu- alizacja istniejącej aplikacji mogą być znacznie większym wyzwaniem. Na szczęście ponownie można użyć wzorca Przyczepa w celu zapewnienia nowej funkcjonalności, która rozszerza starszą aplikację bez jej zmieniania. Wzorzec Przyczepa pokazany na rysunku 2.3 i tym razem ma dwa kontenery: kontener serwujący aplikację oraz kontener, który jest menedżerem konfiguracji. Te dwa kontenery są zgrupowane w kapsule, gdzie współdzielą jeden katalog. W tym wspólnym katalogu przechowywany jest plik konfiguracyjny. Dynamiczna konfiguracja za pomocą przyczepy  27 Poleć książkęKup książkę Rysunek 2.3. Przykład przyczepy zarządzającej dynamiczną konfiguracją Starsza aplikacja po uruchomieniu ładuje swoją konfigurację z systemu pli- ków zgodnie z oczekiwaniami. Menedżer konfiguracji po uruchomieniu spraw- dza interfejs API konfiguracji i szuka różnic między lokalnym systemem pli- ków a konfiguracją przechowywaną w API. Jeśli występują różnice, menedżer konfiguracji pobiera nową konfigurację do lokalnego systemu plików i sy- gnalizuje starszej aplikacji, że powinna ją pobrać. Faktyczny mechanizm tego powiadomienia różni się w zależności od aplikacji. Niektóre aplikacje obser- wują plik konfiguracyjny pod kątem zmian, podczas gdy inne reagują na sy- gnał SIGHUP. W skrajnych przypadkach menedżer konfiguracji może wysłać sygnał SIGKILL, aby przerwać działanie starszej aplikacji. Gdy aplikacja zo- stanie zatrzymana, system orkiestracji kontenerów uruchomi ją ponownie, a wtedy aplikacja załaduje swoją nową konfigurację. Podobnie jak w przypad- ku dodawania obsługi HTTPS do istniejącej aplikacji, ten wzorzec ilustruje, w jaki sposób przyczepa może pomóc w adaptacji istniejących aplikacji do bardziej natywnych dla chmury scenariuszy. 28  Rozdział 2. Wzorzec Przyczepa Poleć książkęKup książkę Modułowe kontenery aplikacji Wybaczę Ci, jeśli na tym etapie uznałeś, że jedynym powodem istnienia wzorca Przyczepa jest dostosowywanie starszych aplikacji w sytuacjach, gdy nie chcemy już modyfikować oryginalnego kodu źródłowego. Chociaż jest to powszechny przypadek użycia tego wzorca, istnieje wiele innych powodów projektowania różnych rzeczy za pomocą przyczep. Innymi istotnymi zaletami korzystania z wzorca Przyczepa są modułowość oraz możliwość ponownego wykorzysta- nia komponentów użytych jako przyczepy. W przypadku wdrażania dowolnej rzeczywistej, niezawodnej aplikacji wymagana jest pewna funkcjonalność umożliwiająca debugowanie lub wykonywanie innych czynności z zakresu za- rządzania aplikacją, takich jak umożliwienie odczytu wszystkich procesów używających zasobów kontenera. Może to być coś na kształt narzędzia wiersza poleceń top. Jednym ze sposobów zapewnienia tej introspekcji jest wymaganie, aby każdy programista implementował interfejs /topz HTTP, który zapewnia odczyt zuży- cia zasobów. Żeby było to łatwiejsze, mógłbyś zaimplementować ten webhook jako charakterystyczną dla danego języka wtyczkę, którą programista może po prostu podłączyć do aplikacji. Jednak nawet w takim przypadku pro- gramista byłby zmuszony podłączyć tę wtyczkę, a Twoja organizacja musiałaby zaimplementować interfejs dla każdego języka, który chce obsługiwać. Bez za- stosowania ekstremalnej dyscypliny takie podejście niewątpliwie doprowadziłoby do wariacji w przypadku różnych języków oraz do braku wsparcia dla tej funk- cjonalności w przypadku używania nowych języków. Zamiast tego funkcjo- nalność topz można wdrożyć jako kontener przyczepy, który współdzieli przestrzeń nazw identyfikatora procesu (ang. process id, PID) z kontenerem apli- kacji. Taki kontener topz może obserwować wszystkie uruchomione procesy i zapewniać spójny interfejs użytkownika. Co więcej, możesz użyć systemu orkie- stracji do automatycznego dodania tego kontenera do wszystkich aplikacji wdrożonych za pośrednictwem tego systemu orkiestracji, aby zapewnić spój- ny zestaw narzędzi dostępny dla wszystkich aplikacji działających w Twojej infrastrukturze. Oczywiście, tak jak przy każdym wyborze technicznym, istnieją kompromisy między tym modularnym wzorcem opartym na kontenerach a przygotowy- waniem własnego kodu dla aplikacji. Podejście oparte na bibliotekach zawsze będzie nieco mniej dostosowane do specyfiki Twojej aplikacji. Oznacza to, że Modułowe kontenery aplikacji  29 Poleć książkęKup książkę może być mniej wydajne lub interfejs API może wymagać adaptacji, aby pa- sował do Twojego środowiska. Porównałbym te kompromisy do różnicy między zakupem odzieży z sieciówki a ubieraniem się u krawca. Ubranie szyte na miarę zawsze będzie Ci pasować, ale poczekasz na nie dłużej i będzie Cię więcej kosztować. Podobnie jest w przypadku kodowania — większość z nas skłoni się raczej ku zakupieniu bardziej uniwersalnego rozwiązania. Oczywiście, jeśli Twoja aplikacja ma ekstremalne wymagania w kwestii wydajności, zawsze możesz wybrać rozwiązanie pisane ręcznie. Część praktyczna: wdrażanie kontenera topz Aby zobaczyć przyczepę topz w akcji, najpierw musisz wdrożyć inny kontener, który będzie działał jako kontener aplikacji. Wybierz jakąś istniejącą aplika- cję, z której korzystasz, i wdróż ją za pomocą Dockera: $ docker run -d obraz_aplikacji wartość_skrótu_kotenera Po uruchomieniu obrazu otrzymasz identyfikator tego konkretnego kontenera. Będzie on wyglądać mniej więcej tak: cccf82b85000… Zawsze możesz też go sprawdzić, używając polecenia docker ps, które wyświetli wszystkie aktualnie uruchomione kontenery. Zakładając, że ukryłeś tę wartość w zmiennej śro- dowiskowej o nazwie APP_ID, możesz uruchomić kontener topz w tej samej przestrzeni nazw PID w następujący sposób: $ docker run --pid=container:${APP_ID} \ -p 8080:8080 \ brendanburns/topz:db0fa58 \ /server --address=0.0.0.0:8080 Spowoduje to uruchomienie przyczepy topz jako kontenera aplikacji w tej samej przestrzeni nazw PID. Zwróć uwagę, że konieczna może być zmiana numeru portu używanego przez przyczepę do serwowania, jeśli kontener aplikacji również działa na porcie 8080. Po uruchomieniu przyczepy możesz wpisać w przeglądarce adres http://localhost:8080/topz, aby uzyskać pełny od- czyt procesów uruchomionych w kontenerze aplikacji wraz z ich wykorzysta- niem zasobów. Możesz łączyć tę przyczepę z innym istniejącym kontenerem, aby za pośred- nictwem interfejsu internetowego łatwo uzyskać wgląd w to, w jaki sposób ten kontener wykorzystuje swoje zasoby. 30  Rozdział 2. Wzorzec Przyczepa Poleć książkęKup książkę Budowanie prostej usługi PaaS za pomocą przyczepy Wzorzec Przyczepa ma więcej zastosowań niż tylko dostosowywanie i moni- torowanie. Może być również używany jako środek do zaimplementowania pełnej logiki aplikacji w uproszczony, modularny sposób. Wyobraź sobie na przykład budowanie prostej platformy jako usługi (ang. platform as a service, PaaS) wokół przepływu pracy git. Po wdrożeniu tej usługi PaaS wysyłanie nowego kodu do repozytorium Git powoduje jego wdrażanie na działających serwerach. Zobaczymy, w jaki sposób wzorzec Przyczepa upraszcza budowa- nie takiej usługi PaaS. Jak już wspomniałem, we wzorcu Przyczepa znajdują się dwa kontenery: głów- ny kontener aplikacji i przyczepa. W naszej prostej aplikacji PaaS głównym kontenerem jest serwer Node.js, który implementuje serwer WWW. Serwer Node.js jest instrumentowany w taki sposób, aby automatycznie przeładowy- wał serwer po aktualizacji nowych plików. Osiąga się to za pomocą narzędzia nodemon (https://nodemon.io/). Kontener przyczepy współdzieli system plików z głównym kontenerem apli- kacji i uruchamia prostą pętlę, która synchronizuje ten system plików z ist- niejącym repozytorium Git: #!/bin/bash while true; do git pull sleep 10 done Oczywiście, ten skrypt może być bardziej złożony i pobierać z określonej gałęzi zamiast po prostu z HEAD. To uproszczenie jest celowe, aby zwiększyć czytelność przykładu. Aplikacja Node.js i przyczepa synchronizacji Git są rozplanowane i wdrożone razem, aby zaimplementować naszą prostą usługę PaaS (zobacz rysunek 2.4). Po wdrożeniu przy każdorazowym przesłaniu nowego kodu do repozytorium Git kod ten jest automatycznie aktualizowany przez przyczepę i ponownie ładowany przez serwer. Budowanie prostej usługi PaaS za pomocą przyczepy  31 Poleć książkęKup książkę Rysunek 2.4. Prosta usługa PaaS oparta na przyczepie Projektowanie przyczep pod kątem modułowości i ponownego użycia We wszystkich przykładach przyczep opisanych szczegółowo w tym rozdziale najważniejsze było to, żeby każdy z nich był modularnym artefaktem wielo- krotnego użytku. Aby można było mówić o sukcesie, przyczepa powinna zapewniać możliwość wielokrotnego użytku w szerokim zakresie aplikacji i wdrożeń. Dzięki modułowej konstrukcji wielokrotnego użytku przyczepy mogą znacznie przyspieszyć budowanie aplikacji. Ta modułowość i możliwość ponownego wykorzystania wymagają jednak skupienia i dyscypliny, podobnie jak uzyskiwanie modułowości podczas two- rzenia wysokiej jakości oprogramowania. Musisz się skoncentrować w szcze- gólności na rozwijaniu trzech obszarów:  parametryzacji kontenerów,  tworzeniu powierzchni API kontenera,  dokumentowaniu działania kontenera. 32  Rozdział 2. Wzorzec Przyczepa Poleć książkęKup książkę Parametryzacja kontenerów Parametryzowanie kontenerów jest najważniejszą rzeczą w kwestii zapewnia- nia modułowości i możliwości wielokrotnego ich używania, niezależnie od tego, czy są one przyczepami, chociaż parametryzowanie przyczep i innych dodatkowych kontenerów jest szczególnie istotne. Co rozumiem przez „parametryzowanie”? Potraktujmy kontener jako funkcję w programie. Ile ma ona parametrów? Każdy parametr reprezentuje dane wej- ściowe, które mogą dostosowywać ogólny kontener do konkretnej sytuacji. Przyjrzyj się na przykład wdrożonej poprzednio przyczepie dodatku SSL. Aby była ona użyteczna, prawdopodobnie będzie potrzebować co najmniej dwóch parametrów: nazwy certyfikatu używanego do zapewnienia SSL oraz portu serwera „starszej” aplikacji, działającego na adresie localhost. Bez tych para- metrów trudno sobie wyobrazić, żeby ten kontener przyczepy był użyteczny w wielu aplikacjach. Podobne parametry istnieją dla wszystkich pozostałych przyczep opisanych w tym rozdziale. Gdy już wiemy, jakich parametrów potrzebujemy, możemy się zastanowić, w jaki sposób będziemy udostępniać je użytkownikom i konsumować wewnątrz kontenera. Istnieją dwa sposoby przekazywania takich parametrów do konte- nera: poprzez zmienne środowiskowe lub wiersz poleceń. Oba sposoby są prawidłowe, ale ja z reguły przekazuję parametry za pomocą zmiennych śro- dowiskowych. Poniżej przykład przekazywania takich parametrów do konte- nera przyczepy: docker run -e=PORT= port -d obraz Oczywiście, dostarczanie wartości do kontenera to tylko część zadania. Kolej- ną kwestią jest używanie tych zmiennych wewnątrz kontenera. Zazwyczaj do tego celu wykorzystywany jest zwykły skrypt powłoki, który ładuje zmienne środowiskowe dostarczone z kontenerem przyczepy i dostosowuje pliki kon- figuracyjne lub parametryzuje bazową aplikację. Jako zmienne środowiskowe można na przykład przekazać ścieżkę do certyfi- katu i port: docker run -e=PROXY_PORT=8080 -e=CERTIFICATE_PATH=/ścieżka/do/cert.crt ... W kontenerze użylibyśmy tych zmiennych do skonfigurowania pliku nginx.conf, który wskazuje serwerowi WWW prawidłową lokalizację pliku i serwera proxy. Projektowanie przyczep pod kątem modułowości i ponownego użycia  33 Poleć książkęKup książkę Definiowanie API każdego kontenera Biorąc pod uwagę, że parametryzujemy kontenery, oczywiste jest, że definiują one „funkcję” wywoływaną za każdym razem, gdy dany kontener jest wyko- nywany. Ta funkcja jest częścią API zdefiniowanego przez kontener, ale ist- nieją również inne części API, w tym wywołania wykonywane przez kontener do innych usług, jak również tradycyjne HTTP lub inne interfejsy API do- starczane przez ten kontener. Przy definiowaniu modułowych kontenerów wielokrotnego użytku trzeba zdawać sobie sprawę, że wszystkie aspekty interakcji kontenera ze światem są częścią interfejsu API zdefiniowanego przez ten kontener wielokrotnego użytku. Podobnie jak w świecie mikrousług, te mikrokontenery opierają się na interfejsach API, aby zapewnić czystą separację kontenera aplikacji i przy- czepy. Dodatkowo celem API jest zagwarantowanie prawidłowego działania wszystkich konsumentów przyczepy wraz z pojawianiem się kolejnych wersji. Posiadanie czystego API dla przyczepy zapewnia także szybszą pracę progra- mistów, ponieważ mają jasną definicję (i, miejmy nadzieję, testy jednostkowe) dla usług dostarczanych w ramach przyczepy. Konkretnym przykładem wagi powierzchni interfejsu API jest omówiona wcześniej przyczepa zarządzania konfiguracją. Przydatną konfiguracją dla tej przyczepy może być parametr UPDATE_FREQUENCY (częstotliwość aktualizacji), który wskazuje, jak często konfiguracja powinna być synchronizowana z sys- temem plików. Oczywiste jest, że jeśli w jakimś późniejszym czasie nazwa pa- rametru zostanie zmieniona na UPDATE_PERIOD (interwał aktualizacji), ta zmiana będzie niezgodna z API przyczepy i z pewnością zakłóci jej działanie dla nie- których użytkowników. Chociaż ten przykład jest oczywisty, nawet subtelniejsze zmiany mogą być niezgodne z interfejsem API przyczepy. Wyobraźmy sobie, że parametr UPDATE_FREQUENCY początkowo pobierał wartość w sekundach. W miarę upływu czasu i na podstawie informacji zwrotnych od użytkowników programista przyczepy doszedł do wniosku, że podawanie wartości w sekundach dla dłuż- szych przedziałów czasu (na przykład minut) było denerwujące. Zmienił więc ten parametr, aby przyjmował łańcuch znaków (10 min, 5 s itp.). Ponieważ stare wartości parametrów (na przykład wartość 10 dla 10 sekund) nie będą parsowane w tym nowym schemacie, jest to zmiana naruszająca interfejs API. Załóżmy jednak, że programista to przewidział, ale ustalił, że wartości bez 34  Rozdział 2. Wzorzec Przyczepa Poleć książkęKup książkę jednostek będą parsowane na milisekundy, podczas gdy wcześniej były par- sowane na sekundy. Nawet ta zmiana, chociaż nie prowadzi do błędu, stanowi naruszenie interfejsu API przyczepy, gdyż prowadzi do znacznie częstszych kontroli konfiguracji i odpowiednio częstszego ładowania danych na serwer konfiguracji w chmurze. Mam nadzieję, że te rozważania przekonały Cię, iż w celu zapewnienia praw- dziwej modułowości trzeba być bardzo świadomym API dostarczanego przez przyczepę, a zmiany naruszające to API nie zawsze będą tak oczywiste jak zmiana nazwy parametru. Dokumentowanie kontenerów Nauczyłeś się już parametryzować kontenery przyczepy w taki sposób, aby były modułowe i wielokrotnego użytku. Poznałeś znaczenie utrzymywania stabilnego API w celu zapewnienia użytkownikom nieprzerwanego prawi- dłowego działania przyczep. Jest jeszcze jeden krok na drodze do budowania modułowych kontenerów wielokrotnego użytku: zagwarantowanie użytkow- nikom możliwości korzystania z nich. Podobnie jak w przypadku bibliotek oprogramowania, kluczem do zbudowa- nia czegoś naprawdę użytecznego jest wyjaśnienie, jak tego używać. Budowa- nie elastycznego, niezawodnego kontenera modułowego jest mało przydatne, jeśli nikt nie wie, jak z niego korzystać. Niestety nie ma zbyt wielu formalnych narzędzi do dokumentowania obrazów kontenerów, ale istnieje kilka dobrych praktyk, które można zastosować. W przypadku każdego obrazu kontenera najbardziej oczywistym miejscem szukania dokumentacji jest plik Dockerfile, na podstawie którego kontener zo- stał zbudowany. Niektóre części pliku Dockerfile już dokumentują sposób dzia- łania kontenera. Jednym z przykładów jest dyrektywa EXPOSE wskazująca porty, na których obraz nasłuchuje. Chociaż dyrektywa EXPOSE nie jest konieczna, dobrą praktyką jest umieszczenie jej w pliku Dockerfile oraz dodanie komen- tarza wyjaśniającego, co dokładnie nasłuchuje na tym porcie, na przykład: ... # Główny serwer WWW działa na porcie 8080 EXPOSE 8080 ... Projektowanie przyczep pod kątem modułowości i ponownego użycia  35 Poleć książkęKup książkę Ponadto jeśli do sparametryzowania kontenera używasz zmiennych środowi- skowych, możesz skorzystać z dyrektywy ENV, aby ustawić wartości domyślne dla tych parametrów i udokumentować ich użycie: ... # Parametr PROXY_PORT wskazuje port na adresie localhost, do którego ma być przekierowany ruch. ENV PROXY_PORT 8000 ... Należy także zawsze używać dyrektywy LABEL w celu dodawania do obrazu meta- danych, takich jak adres e-mail opiekuna, strona internetowa i wersja obrazu: ... LABEL org.label-schema.vendor = nazwisko@firma.com LABEL org.label.url = http://obrazy.firma.com/mój_fajny_obraz LABEL org.label-schema.version = 1.0.3 ... Nazwy tych etykiet pochodzą ze schematu ustalonego przez projekt Label Schema (http://label-schema.org/rc1/). W ramach projektu powstaje wspólny zestaw dobrze znanych etykiet. Dzięki zastosowaniu wspólnej systematyki etykiet obrazów wiele różnych narzędzi może polegać na tych samych meta- informacjach, aby wizualizować, monitorować i prawidłowo wykorzystywać aplikację. Przyjmując wspólne pojęcia, można używać zestawu narzędzi opra- cowanych przez społeczność bez modyfikowania obrazu. Oczywiście, możesz również wstawić różne dodatkowe etykiety, które mają sens w kontekście Twojego obrazu. Podsumowanie W tym rozdziale wprowadziłem wzorzec Przyczepa, który służy do łączenia kontenerów na pojedynczej maszynie. W tym wzorcu kontener przyczepy rozszerza kontener aplikacji, aby dodać określoną funkcjonalność. Przyczepy można wykorzystywać do aktualizowania istniejących starszych aplikacji, gdy ich zmiana jest zbyt kosztowna. Ponadto można je stosować do tworzenia modułowych kontenerów narzędziowych, które standaryzują implementacje typowych funkcjonalności. Takie kontenery narzędziowe mogą być ponownie wykorzystywane w dużej liczbie aplikacji, gdyż zwiększają spójność i obniżają koszty opracowania każdej z nich. Następne rozdziały wprowadzają kolejne wzorce jednowęzłowe, które demonstrują inne zastosowania dla modułowych kontenerów wielokrotnego użytku. 36  Rozdział 2. Wzorzec Przyczepa Poleć książkęKup książkę
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Projektowanie systemów rozproszonych. Wzorce i paradygmaty dla skalowalnych, niezawodnych usług
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ą: