Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00460 005727 18996180 na godz. na dobę w sumie
Ciągłe dostarczanie oprogramowania w języku Java. Najlepsze narzędzia i praktyki wdrażania kodu - książka
Ciągłe dostarczanie oprogramowania w języku Java. Najlepsze narzędzia i praktyki wdrażania kodu - książka
Autor: , Liczba stron: 400
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-283-5633-7 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> inne - programowanie
Porównaj ceny (książka, ebook (-35%), audiobook).

W ciągu ostatnich lat radykalnie zmieniły się wymagania i oczekiwania biznesowe wobec oprogramowania. Kluczowymi wartościami są innowacyjność, szybkość i czas wejścia na rynek. Do spełnienia tych wymagań konieczne okazały się nowe architektury i modele tworzenia kodu. Metodyka ciągłego dostarczania, zwanego też CD, polega na tworzeniu w krótkich cyklach wartościowych i solidnych produktów. Funkcjonalności są dodawane w małych krokach, a oprogramowanie można wydawać niezawodnie w dowolnej chwili. To sprawia, że można też szybko otrzymywać informacje zwrotne. Jednak taki sposób pracy wymaga odpowiednich ram organizacyjnych, a zespół projektowy musi przyswoić nieco inny od tradycyjnego styl pracy.

Ta książka jest praktycznym przewodnikiem, dzięki któremu programiści Javy opanują techniki potrzebne do pomyślnego zastosowania metody ciągłego dostarczania. Opisano tu najlepsze zasady budowy architektury oprogramowania, automatycznej kontroli jakości, pakowania aplikacji i wdrażania ich w różnych środowiskach produkcyjnych. Szczególną uwagę poświęcono testowaniu oprogramowania: przedstawiono całą gamę metodyk testowania, opisano ich zastosowanie i znaczenie w cyklu życia aplikacji. Ciekawym elementem książki są informacje o złych praktykach i antywzorcach wraz ze wskazówkami dotyczącymi rozwiązywania tego rodzaju problemów.

W tej książce między innymi:

Java i CD: tak zdobędziesz prawdziwą przewagę!

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

Darmowy fragment publikacji:

Tytuł oryginału: Continuous Delivery in Java: Essential Tools and Best Practices for Deploying Code to Production Tłumaczenie: Krzysztof Bąbol (rozdz. 1 – 5), Andrzej Watrak (wstęp, rozdz. 8 – 13), Lech Lachowski (rozdz. 6, 7, 14, 15) ISBN: 978-83-283-5633-7 © 2019 Helion S.A. Authorized Polish translation of the English edition of Continuous Delivery in Java ISBN 9781491986028 © 2019 Daniel Bryant and Cosota Team Ltd. 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/ciados Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję. Pliki z przykładami omawianymi w książce można znaleźć pod adresem: ftp://ftp.helion.pl/przyklady/ciados.zip Printed in Poland. • Kup książkę • Poleć książkę • Oceń książkę • Księgarnia internetowa • Lubię to! » Nasza społeczność Spis treści Słowa wstępne ......................................................................................................... 13 Wstęp ....................................................................................................................... 17 Ogólny zarys Dlaczego? Bo daje możliwości programistom Szybka informacja zwrotna pozwala ograniczyć zmiany kontekstu Automatyczne, powtarzalne i niezawodne wydania Uściślenie definicji ukończenia 1. Ciągłe dostarczanie? Dlaczego? Czym jest? ................................................................. 21 21 22 22 22 23 24 24 28 29 29 Podstawowe etapy potoku budowy Wpływ technologii kontenerów Zmiany we współczesnych architekturach Czym jest? Badamy typowy potok budowy Podsumowanie Wymagania współczesnych aplikacji Java 2. Ewolucja programowania w języku Java .................................................................... 31 31 32 32 33 33 34 35 35 Potrzeba szybkości i stabilności biznesowej Rozwój ekonomii interfejsów API Szanse i koszty chmury Przywrócenie modularności: wykorzystanie niewielkich usług Wpływ na ciągłe dostarczanie Ewolucja platform wdrożeniowych w języku Java Archiwa WAR i EAR: era dominacji serwerów aplikacji Wykonywalne pliki JAR z zależnościami: powstanie metodologii dwunastu aspektów Obrazy kontenerów: ulepszenie przenośności (i zwiększenie złożoności) Funkcja jako usługa: pojawienie się przetwarzania „bezserwerowego” Wpływ platform na ciągłe dostarczanie 36 37 37 38 3 Poleć książkęKup książkę Metodyki DevOps, SRE oraz Release Engineering Rozwój i utrzymanie Site Reliability Engineering Inżynieria wydawnicza oprogramowania Współodpowiedzialność, metryki i wgląd Podsumowanie 39 39 40 42 43 44 Fundamenty dobrej architektury Architektura nakierowana na elastyczność biznesową Zła architektura ogranicza dynamikę biznesową Złożoność i koszt zmian Luźne sprzężenie Wysoka spójność Sprzężenie, spójność i ciągłe dostarczanie 3. Projektowanie architektury pod kątem ciągłego dostarczania .................................... 45 45 45 47 47 49 49 50 50 51 51 52 52 55 56 57 57 Projektowanie aplikacji natywnych dla chmury według metodologii 12 aspektów Doskonalenie wyczucia mechaniki Projektowanie i ciągłe testowanie pod kątem awarii Tworzenie interfejsów API metodą od zewnątrz do wewnątrz Dobre interfejsy API pomagają w ciągłym testowaniu i dostarczaniu Najlepsze rozwiązania dla aplikacji zorientowanych na API Platformy wdrażania a architektura Podążanie w kierunku niewielkich usług Wyzwania w dostarczaniu aplikacji monolitycznych Mikrousługi: architektura zorientowana na usługi spotyka się z projektowaniem dziedzinowym Funkcje, architektura Lambda i nanousługi Architektura: „wszystko to, co trudno zmienić” Podsumowanie 58 59 60 60 Funkcje zapewniane przez platformę Niezbędne procesy programistyczne Platformy oparte o tradycyjną infrastrukturę 4. Platformy wdrożeniowe, infrastruktura i ciągłe dostarczanie aplikacji Java ................ 63 63 64 65 65 Komponenty tradycyjnej platformy 66 Wyzwania platform opartych o tradycyjną infrastrukturę Korzyści z bycia tradycyjnym 66 Ciągła integracja i dostarczanie na platformach opartych o tradycyjną infrastrukturę 67 67 68 69 70 71 Platforma chmury (IaaS) Zaglądamy w chmurę Wyzwania chmury Korzyści z chmury Ciągłe dostarczanie w chmurze 4 (cid:95) Spis treści Poleć książkęKup książkę Platforma jako usługa Zaglądamy w usługę PaaS Wyzwania platformy PaaS Korzyści z platformy PaaS Ciągła integracja i dostarczanie a model PaaS Kontenery (Docker) Komponenty platformy kontenerów Wyzwania technologii kontenerów Korzyści z kontenerów Ciągłe dostarczanie kontenerów Kubernetes Podstawowe koncepcje platformy Kubernetes Wyzwania platformy Kubernetes Korzyści z platformy Kubernetes Ciągłe dostarczanie na platformie Kubernetes Funkcja jako usługa (funkcje bezserwerowe) Koncepcje platformy FaaS Wyzwania platformy FaaS Korzyści z platformy FaaS Ciągła integracja i dostarczanie a model FaaS Praca z infrastrukturą jako kodem Podsumowanie 72 72 73 75 75 75 76 76 78 78 78 79 80 81 81 81 82 83 84 84 85 86 Podział procesu budowania Automatyzacja budowania Zależności budowania Zależności zewnętrzne Projekty wielomodułowe Wiele repozytoriów (czy jedno)? Wtyczki Wydawanie i publikacja artefaktów Przegląd narzędzi do budowania kodu Java 5. Budowanie aplikacji w języku Java ............................................................................ 87 87 88 89 92 93 93 94 95 95 95 98 102 105 107 107 108 109 Ant Maven Gradle Bazel, Pants i Buck Inne narzędzia do budowania oparte o JVM: SBT i Leiningen Make Wybór narzędzia do budowania Podsumowanie Spis treści (cid:95) 5 Poleć książkęKup książkę Wywołania HTTP i manipulacja danymi JSON Polecenia Linuksa, powłoki Bash i podstawowego interfejsu wiersza poleceń Użytkownicy, uprawnienia i grupy Praca z systemem plików Przeglądanie i edycja tekstu Wszystko razem: przekierowania, potoki i filtry Wyszukiwanie tekstu i manipulowanie nim: grep, awk i sed Narzędzia diagnostyczne: top, ps, netstat i iostat 6. Dodatkowe narzędzia i umiejętności wykorzystywane do budowania aplikacji ......... 111 111 112 115 117 118 119 120 121 121 124 127 128 128 128 129 129 130 Narzędzie xargs Potoki i filtry Pętle Warunki Narzędzie curl Narzędzie HTTPie Narzędzie jq Podstawy pisania skryptów Podsumowanie Budowanie archiwum JAR krok po kroku Budowanie wykonywalnego fat JAR (uber JAR) 7. Pakowanie aplikacji do wdrożenia ........................................................................... 131 131 135 135 138 139 140 141 142 142 Wtyczka Maven Shade Budowanie plików uber JAR przy użyciu projektu Spring Boot Skinny JAR — gdy zdecydujesz się nie budować plików uber JAR Budowanie plików WAR Pakowanie dla chmury Gotowanie konfiguracji: wypiekanie lub smażenie maszyn Budowanie pakietów RPM i DEB systemu operacyjnego Dodatkowe narzędzia kompilowania pakietów systemu operacyjnego (z obsługą systemu Windows) Tworzenie obrazów maszyn dla wielu chmur za pomocą programu Packer Dodatkowe narzędzia do tworzenia obrazów maszyn Budowanie kontenerów Tworzenie obrazów kontenerów za pomocą narzędzia Docker Fabrykowanie obrazów Docker za pomocą fabric8 Pakowanie aplikacji Java FaaS Podsumowanie 6 (cid:95) Spis treści 145 147 149 150 150 151 153 155 Poleć książkęKup książkę Maszyny wirtualne oraz narzędzia Vagrant i Packer Instalacja narzędzia Vagrant Utworzenie pliku Vagrantfile Wzorzec 3.: pudełkowe środowisko produkcyjne Kontenery: Kubernetes, minikube i Telepresence Wyzwania związane z lokalnym tworzeniem oprogramowania Imitacje, atrapy i wirtualizacja usług Wzorzec 1.: profile, imitacje i atrapy Imitowanie usług za pomocą biblioteki Mockito Wzorzec 2.: wirtualizacja usług i symulacja interfejsu API Wirtualizacja usług za pomocą narzędzia Hoverfly 8. Praca w lokalnym odpowiedniku środowiska produkcyjnego .....................................157 157 158 158 159 161 162 165 166 166 168 169 169 170 172 174 174 174 175 176 178 179 179 179 182 185 186 186 189 Przykładowa aplikacja Docker Java Shop Tworzenie aplikacji Java i obrazów kontenerów Wdrożenie kontenera na platformie Kubernetes Prosty test usługi Utworzenie pozostałych usług Wdrożenie całej usługi Java na platformie Kubernetes Kontrola wdrożonej aplikacji Telepresence: praca zdalna i lokalna Wzorzec 4.: dzierżawa środowiska Instalacja narzędzia SAM Local Tworzenie funkcji AWS Lambda Testowanie obsługi zdarzeń za pomocą funkcji AWS Lambda Testowanie funkcji za pomocą narzędzia SAM Local Funkcja jako usługa: AWS Lambda i SAM Local FaaS: usługa Azure Functions i edytor Visual Studio Code Instalacja najważniejszych komponentów Azure Functions Lokalne kompilowanie i testowanie funkcji Testowanie lokalnych i zewnętrznych funkcji za pomocą edytora Visual Studio Code Podsumowanie 191 192 Co to jest ciągła integracja oprogramowania? Implementacja ciągłej integracji oprogramowania Centralny i rozproszony system kontroli wersji Przewodnik po systemie Git 9. Ciągła integracja: pierwsze kroki w tworzeniu procesu kompilacji kodu .....................193 193 194 194 196 196 198 Najważniejsze polecenia systemu Git Hub: podstawowe narzędzie w systemach Git i GitHub Spis treści (cid:95) 7 Poleć książkęKup książkę Efektywne korzystanie z systemu DVCS Programowanie pniowe Odgałęzienia funkcjonalne Gitflow Nie ma recepty na wszystko, czyli jak wybrać odpowiednią strategię odgałęziania Przeglądanie kodu Cele przeglądania kodu Automatyzacja przeglądu kodu: analizatory PMD, Checkstyle i FindBugs Przeglądanie wniosków o zmiany Automatyzacja kompilacji Jenkins Zaangażowanie zespołu Regularne konsolidowanie kodu „Zatrzymać produkcję!”, czyli obsługa nieudanych kompilacji Nie ignoruj testów Kompilacja musi być szybka Ciągła integracja platformy (infrastruktura jako kod) Podsumowanie 200 200 201 201 202 204 205 207 210 211 212 213 214 214 214 215 215 216 Wprowadzenie do aplikacji Extended Java Shop Rozdzielenie wdrożenia i wydania aplikacji Wdrażanie aplikacji Utworzenie obrazu kontenera Mechanizm wdrażania Wszystko zaczyna się (i kończy) na kontroli stanu Strategie wdrożeniowe Praca z niezarządzanymi klastrami Modyfikacje baz danych Wydawanie funkcjonalności 10. Proces wdrażania i wydawania oprogramowania ..................................................... 217 217 220 220 221 224 233 237 246 249 252 253 255 257 261 262 263 264 265 266 Flagi funkcjonalności Wersjonowanie semantyczne Kompatybilność wsteczna i wersje interfejsu API Wielofazowe aktualizacje Zarządzanie konfiguracją i poufnymi danymi „Zaprasowana” konfiguracja Zewnętrzna konfiguracja Przetwarzanie poufnych danych Podsumowanie 8 (cid:95) Spis treści Poleć książkęKup książkę Utworzenie odpowiedniej pętli zwrotnej Testy kontraktów klienckich Kontrakty REST API Kontrakty komunikatów Testy komponentów Programowanie zorientowane na działanie Imitowanie i wirtualizowanie zewnętrznych usług Wszystko razem Żółwie są wszędzie, aż po sam koniec Transakcje syntetyczne Testy kompleksowe Testy akceptacyjne Po co testować oprogramowanie? Co testować? Wprowadzenie do kwadrantów zwinnego testowania Ciągłe testowanie oprogramowania 11. Testy funkcjonalne: sprawdzenie poprawności i akceptacja oprogramowania ............267 267 267 269 270 270 272 272 274 275 278 278 279 280 283 285 285 286 287 288 289 291 291 292 293 294 295 296 296 296 297 297 298 298 299 301 301 303 Wbudowane magazyny danych Kolejki komunikatów umieszczane w pamięci Dublerzy testowi Tworzenie wewnętrznych zasobów lub interfejsów Testy wewnątrz- i zewnątrzprocesowe Zebranie wszystkiego w jeden proces Jak dużo testów trzeba wykonać? Podsumowanie Weryfikowanie zewnętrznych interakcji Testy odporności na błędy Testy integracyjne Testy jednostkowe Towarzyskie testy jednostkowe Samotne testy jednostkowe Niestabilne testy Dane Tymczasowo niedostępne zasoby Niedeterministyczne zdarzenia Gdy nic nie można zrobić Testy „do wewnątrz” i „na zewnątrz” Testy „do wewnątrz” Testy „na zewnątrz” Spis treści (cid:95) 9 Poleć książkęKup książkę Testy wydajnościowe i obciążeniowe Testowanie wydajności przy użyciu Apache Benchmark Testy obciążeniowe z użyciem narzędzia Gatling Po co testować wymagania niefunkcjonalne? Jakość kodu Jakość architektury ArchUnit: testy jednostkowe architektury Wyliczanie wskaźników jakościowych projektu za pomocą biblioteki JDepend 12. Testy jakościowe systemu: weryfikacja wymagań niefunkcjonalnych ........................ 305 305 306 306 307 308 310 311 312 317 318 322 325 329 332 333 334 335 336 Wywoływanie chaosu w środowisku produkcyjnym Wywoływanie chaosu w środowisku przedprodukcyjnym Jak dużo testów wymagań niefunkcjonalnych trzeba wykonać? Podsumowanie Weryfikacja bezpieczeństwa na poziomie kodu Weryfikacja zależności Luki w bezpieczeństwie platform wdrożeniowych Kolejny krok: modelowanie zagrożeń Bezpieczeństwo, podatności i zagrożenia Testowy chaos Obserwowalność i ciągłe dostarczanie oprogramowania Projektowanie obserwowalnych systemów Wskaźniki Po co obserwować aplikację? Obiekty obserwacji: aplikacja, sieć, serwer Metody obserwacji: monitorowanie, logowanie i śledzenie Alarmy 13. Obserwowalność aplikacji: monitorowanie, logowanie i śledzenie ............................ 337 337 338 338 340 340 341 342 343 343 344 345 346 347 347 348 349 350 351 352 353 353 Ślady, przęsła i bagaże Śledzenie aplikacji Java: OpenZipkin, Spring Cloud Sleuth i OpenCensus Dobre praktyki śledzenia systemów Rodzaje wskaźników Dropwizard Metrics Spring Boot Actuator Micrometer Dobre praktyki tworzenia wskaźników Formaty logów SLF4J Log4j 2 Dobre praktyki logowania Śledzenie zapytań Logowanie 10 (cid:95) Spis treści Poleć książkęKup książkę Śledzenie wyjątków Airbrake Narzędzia do monitorowania systemu collectd rsyslog Sensu Zbieranie i zapisywanie danych Prometheus Elastic-Logstash-Kibana Wizualizacja danych Wizualizacja dla biznesu Wizualizacja dla administratorów Wizualizacja dla programistów Podsumowanie 354 355 356 356 356 357 357 358 358 359 359 360 361 362 Czynniki ciągłego dostarczania Wybór projektu migracji Świadomość sytuacyjna Framework Cynefin i ciągłe dostarczanie Wszystkie modele są złe, ale niektóre są przydatne 14. Migracja do ciągłego dostarczania ............................................................................365 365 366 367 368 369 370 371 372 374 375 375 376 379 Wstępne organizowanie ciągłego dostarczania Pomiar ciągłego dostarczania Zacznij od niewielkich rzeczy, eksperymentuj, ucz się, udostępniaj i powtarzaj Szersze wdrożenie: kierowanie wprowadzaniem zmian Dodatkowe porady i wskazówki Złe praktyki i typowe antywzorce Brzydka architektura: naprawiać czy nie naprawiać Podsumowanie 15. Ciągłe dostarczanie i ciągłe doskonalenie ..................................................................381 381 382 382 383 384 385 385 386 Zacznij od punktu, w którym jesteś Opieraj się na solidnych podstawach technicznych Ciągłe dostarczanie wartości (Twój najwyższy priorytet) Zwiększenie współodpowiedzialności za oprogramowanie Promuj szybką informację zwrotną i eksperymentowanie Rozwijaj ciągłe dostarczanie w organizacji Ciągłe doskonalenie Podsumowanie Skorowidz ................................................................................................................389 Spis treści (cid:95) 11 Poleć książkęKup książkę 12 (cid:95) Spis treści Poleć książkęKup książkę ROZDZIAŁ 8. Praca w lokalnym odpowiedniku środowiska produkcyjnego Zanim zaczniesz budować proces ciągłego dostarczania oprogramowania, musisz sprawdzić, czy jesteś w stanie skutecznie oraz wydajnie pracować nad kodem i systemami na lokalnym kompute- rze. W tym rozdziale opisano kilka związanych z tym problemów, pojawiających się szczególnie w nowoczesnych systemach rozproszonych o architekturze opartej na usługach. Przedstawione zostały również techniki, takie jak imitowanie (ang. mocking) usług, wirtualizacja usług, wirtuali- zacja infrastruktury (zarówno za pomocą maszyn wirtualnych, jak i kontenerów) oraz lokalne rozwijanie aplikacji FaaS. Wyzwania związane z lokalnym tworzeniem oprogramowania Jako programista Java zapewne tradycyjną monolityczną aplikację WWW zazwyczaj rozwijasz w lokalnym, prosto skonfigurowanym środowisku. Jego przygotowanie najczęściej polega na za- instalowaniu systemu operacyjnego, pakietu JDK, narzędzi kompilacyjnych (Maven lub Gradle) oraz środowiska IDE, np. IntelliJ IDEA lub Eclipse. Czasami potrzebne jest dodatkowo oprogra- mowanie pośredniczące, baza danych lub serwer aplikacyjny. Takie środowisko sprawdza się w przypadku pojedynczej aplikacji Java, ale co robić, gdy trzeba zbudować system składający się z wielu usług, przeznaczony do uruchomienia w chmurze, na platformie kontenerowej lub bezserwerowej? Kiedy przymierzasz się do tworzenia aplikacji opartej na wielu usługach, najbardziej logiczną de- cyzją jest zaadaptowanie lokalnych praktyk programistycznych do pracy nad każdą nową usługą. Jednak — jak to zwykle bywa w IT — ręcznie replikując środowisko, nie zajdziesz daleko. Naj- większy problem z takim podejściem jest związany z kosztami integracji i testów oprogramowa- nia. Jeżeli nawet każdą usługę można przetestować pod kątem integracji z innymi komponenta- mi, to trudno zainicjować i skoordynować konfigurację testową, gdy usług jest więcej niż kilka. W takim przypadku trzeba utworzyć lokalną replikę zewnętrznej usługi (klonując ją z repozyto- rium systemu kontroli wersji, kompilując i uruchamiając), manipulować jej stanem, wykonywać testy i na koniec weryfikować jej stan po uruchomieniu w zewnętrznym systemie. 157 Poleć książkęKup książkę Problemy z lokalnymi skryptami konfiguracyjnymi W przeszłości często spotykaliśmy programistów, którzy starali się rozwiązywać problemy z lokalną inicjacją środowiska poprzez tworzenie prostych skryptów (Bash, Groovy itp.) wiążących wszystkie narzędzia i inicjujące dane testowe. Z naszego doświadczenia wynika, że takie skrypty szybko stają się prawdziwą udręką, ponie- waż trudno je utrzymywać. Dlatego nie zalecamy takiego podejścia. Wspominamy o nim tylko dlatego, ponieważ stanowi punkt wyjścia do dalszej dyskusji. Imitacje, atrapy i wirtualizacja usług Podstawowym podejściem, jakie możesz zastosować do skalowania lokalnego środowiska robo- czego, jest imitowanie usług. To technika znana wielu programistom. W tym podrozdziale do- wiesz się, jak ją najlepiej wykorzystać. Poznasz również inną, nie tak szeroko stosowaną technikę, ale bardzo przydatną podczas pracy z wieloma zewnętrznymi usługami i interfejsami API, czyli wirtualizację. Wzorzec 1.: profile, imitacje i atrapy Jeżeli potrafisz tworzyć kod za pomocą platformy Spring opartej na maszynach JVM, na pewno nieobce jest Ci pojęcie profilu. Profil to zestaw różnych ustawień konfiguracyjnych, które aplikuje się podczas kompilowania lub uruchamiania kodu. Za pomocą profili nim można tworzyć imita- cje lub atrapy interfejsów zewnętrznych usług i wykorzystywać je w lokalnym środowisku. W za- leżności od potrzeb profile można przełączać i korzystać z usług lokalnych lub produkcyjnych. Takie podejście stosuje się np. podczas rozwijania usługi witryna-sklepu uzależnionej od usługi wyszukiwanie-produktu. Interfejs tej ostatniej usługi jest ściśle zdefiniowany, więc można utwo- rzyć kilka opisanych niżej profili i wykorzystywać je do automatycznego testowania kodu za po- mocą narzędzia Maven. bez-wyszukiwania Taki profil może zawierać prostą imitację usługi wyszukiwanie-produktu. Imitacja ta (utwo- rzona np. za pomocą biblioteki Mockito) nie wykonuje żadnych operacji i zwraca puste wyniki. Przydaje się wtedy, gdy lokalnie rozwijany kod korzysta z usługi wyszukiwanie-produktu, ale zwracane przez nią wyniki nie są ważne. wyszukiwanie-parametryzowane Taki profil może zawierać atrapę usługi wyszukiwanie-produktu, przy czym atrapę tę można parametryzować tak, aby podczas testów zwracała określone wyniki (np. jeden produkt, dwa produkty, produkt o określonych właściwościach, produkt uszkodzony itp.). Atrapa może być zwykłą klasą Java, która odczytuje z zewnętrznego pliku JSON uprzednio przygotowane wyniki wyszukiwania. Jest to bardzo przydatne podejście, gdy jednak atrapa stanie się bar- dziej skomplikowana (będzie zawierała mnóstwo instrukcji warunkowych), wtedy warto przyjrzeć się innemu wzorcowi — wirtualizacji usługi. 158 (cid:95) Rozdział 8. Praca w lokalnym odpowiedniku środowiska produkcyjnego Poleć książkęKup książkę środowisko-produkcyjne Ten profil umożliwia korzystanie z rzeczywistej, produkcyjnej usługi wyszukiwanie-produktu, implementowanie przetwarzania obiektów, obsługi błędów itp. Opisany tu wzorzec obejmuje też korzystanie z wbudowanych w proces tymczasowych maga- zynów danych oraz oprogramowania pośredniczącego, jednak nie są to imitacje ani atrapy. Uruchamiając taki proces, można korzystać z komponentu w taki sam sposób, jak z jego rze- czywistej instancji, przy czym nakład pracy związanej z jego zainicjowaniem i konfiguracją jest znacznie mniejszy. Zalety wbudowanych baz danych i oprogramowania pośredniczącego Za pomocą imitacji i atrap można skutecznie testować kod, natomiast w przypadku korzystania z ma- gazynów danych i oprogramowania pośredniczącego trzeba często tworzyć skomplikowane imitacje lub symulować skomplikowane działanie usługi. Jeżeli napotkasz tego rodzaju problemy, zalecamy sprawdzenie, czy magazyn lub oprogramowanie można uruchomić w trybie „wbudowanym” w proces lub pamięć. Można wtedy korzystać z wszystkich funkcjonalności rzeczywistej usługi, ale obciążenie systemu jest znacznie mniejsze niż po uruchomieniu pełnej wersji aplikacji. Aplikacja w tym trybie zazwyczaj uruchamia się szybciej, a jej czasy odpowiedzi są krótsze (ponieważ dane znajdują się w pamięci i nie trzeba ich odczytywać z dysku). Konfigurację aplikuje się przy każdorazowym uruchamianiu procesu. Wadą tego trybu jest niewielki zbiór danych (który musi zmieścić się w pamięci), a wprowadzane w nim zmiany podczas każdego testu nie są zapisywane w sposób trwały. Do testowania kodu i tworzenia zautomatyzowanych pakietów testowych z powodzeniem stosowaliśmy następujące wbudowane aplikacje. (cid:120) H2 i HSQL jako testowy zamiennik bazy MySQL (pamiętaj o różnicach pomiędzy implementacjami). (cid:120) Stubbed Cassandra jako zamiennik Apache Cassandra. (cid:120) Baza ElasticSearch uruchomiona jako pojedynczy, wbudowany węzeł. (cid:120) Apache Qpid jako wbudowany zamiennik kolejek RabbitMQ i ActiveMQ. (cid:120) Platforma Localstack zawierająca wbudowane wersje różnych usług baz danych AWS, m.in. Dy- namoDB i Kinesis. Jeżeli wybranej bazy danych lub oprogramowania pośredniczącego nie można uruchomić w trybie wbudowanym w proces lub pamięć albo do testów potrzebne są duże ilości danych, wtedy można za- stosować projekt testcontainers (https://www.testcontainers.org), umieścić wykorzystywane kompo- nenty w kontenerach i uruchamiać je za pomocą narzędzia JUnit. Imitowanie usług za pomocą biblioteki Mockito Jedną z najpopularniejszych bibliotek imitacyjnych dla języka Java jest Mockito. Jej najnowsza wersja 2.0+ oferuje elastyczną platformę do weryfikowania interakcji z zależnymi komponentami oraz tworzenia atrap metod. Imitacje, atrapy i wirtualizacja usług (cid:95) 159 Poleć książkęKup książkę Weryfikowanie interakcji Tworząc kod wykorzystujący zewnętrzne komponenty (zależności), często trzeba sprawdzać, czy aplikacja właściwie się z nimi komunikuje, szczególnie w specyficznych scenariuszach (np. pomyśl- nego lub problematycznego wykonania pewnej operacji). Listing 8.1 przedstawia przykładowy test. Listing 8.1. Weryfikacja interakcji z klasą List za pomocą atrapy utworzonej z użyciem biblioteki Mockito import static org.mockito.Mockito.*; // Utworzenie imitacji komponentu. List mockedList = mock(List.class); // Zastosowanie obiektu-imitacji, który nie zgłasza wyjątku „nieoczekiwana interakcja”. mockedList.add( jeden ); mockedList.clear(); // Selektywna, jawna i czytelna weryfikacja. verify(mockedList).add( jeden ); verify(mockedList).clear(); Użyte w kodzie asercje dotyczą działania aplikacji (tj. sprawdzają, czy aplikacja reaguje poprawnie w określonej sytuacji lub w zadanych warunkach). Tworzenie atrap metod Oprócz testowania działania aplikacji często trzeba weryfikować wyniki, stany lub dane zwracane przez zewnętrzne usługi lub rozwijane (testowane) metody. Taka sytuacja pojawia się zazwyczaj pod- czas implementowania skomplikowanego algorytmu lub korzystania z wielu zewnętrznych usług, przy czym nie tyle ważne są poszczególne interakcje, co końcowy wynik. Ilustruje to listing 8.2. Listing 8.2. Atrapa klasy LinkedList zwracająca wynik // Można tworzyć atrapy nie tylko interfejsów, ale również klas. LinkedList mockedList = mock(LinkedList.class); // Atrapę tworzy się przed wywołaniem metody. when(mockedList.get(0)).thenReturn( pierwszy ); // Poniższa instrukcja zwraca wartość true. assertThat(mockedList.get(0), is( pierwszy ); // Poniższa instrukcja wyświetla wynik null , ponieważ metoda get(999) nie ma atrapy. System.out.println(mockedList.get(999)); Jest to prosty przykład asercji weryfikującej wartość (tutaj zwracaną bezpośrednio przez atrapę metody), a nie interakcję. Kontroluj złożoność imitacji Jeżeli stwierdzisz, że imitacja coraz gorzej odzwierciedla rzeczywistą aplikację lub usługę albo coraz więcej czasu poświęcasz na jej tworzenie, oznacza to, że jest ona zbyt skomplikowana i powinieneś zastosować inną technikę lub narzędzie. Pamiętaj, że oprogramowanie jest dla człowieka, a nie odwrotnie! W tym rozdziale pokazaliśmy tylko drobny fragment funkcjonalności oferowanych przez bardzo przydatną bibliotekę, jaką jest Mockito. 160 (cid:95) Rozdział 8. Praca w lokalnym odpowiedniku środowiska produkcyjnego Poleć książkęKup książkę Wzorzec 2.: wirtualizacja usług i symulacja interfejsu API Gdy imitacje lub atrapy zewnętrznych usług stają się coraz bardziej skomplikowane, jest to sy- gnał, że lepszym rozwiązaniem może być wirtualizacja usługi. Jeżeli atrapa zawiera mnóstwo in- strukcji warunkowych, staje się źródłem nieporozumień z osobami modyfikującymi przygotowa- ne dane, powoduje, że testy kończą się niepowodzeniem i coraz trudniej ją utrzymywać, znaczy to, że atrapa jest zbyt skomplikowana. Wirtualizacja jest techniką umożliwiającą symulowanie zewnętrznej usługi bez konieczności jej uruchamiania i korzystania z niej. To podejście różni się od uruchamiania usługi wbudowanej w proces lub pamięć, ponieważ wirtualna usługa zachowuje się w uprzednio zadany sposób lub zgodnie z zarejestrowanymi interakcjami aplikacji z rzeczywi- stą usługą. Z wykorzystaniem wirtualizacji można efektywniej niż za pomocą imitacji lub atrapy symulować działanie skomplikowanej usługi. Technika ta z powodzeniem sprawdza się w różnych scenariu- szach, np. gdy usługa zwraca skomplikowane dane (lub ich duże ilości), gdy nie ma do niej dostępu (jest świadczona przez zewnętrzny podmiot lub jest to usługa SaaS) lub gdy komunikuje się z nią wiele innych usług i łatwiej udostępniać wirtualną usługę niż tworzyć imitacje lub atrapy kodu. Do wirtualizowania usług służą następujące narzędzia. Mountebank Jest to aplikacja JavaScript/Node.js stanowiąca według jej twórców „niezależną od systemu operacyjnego, wieloprotokołową platformę do testowania aplikacji w locie”. Można ją stoso- wać do wirtualizowania usług wykorzystujących protokoły HTTP, HTTPS, TCP i SNMP. Platforma ma prosty w użyciu interfejs API i choć czasami wymaga napisania dość rozbudo- wanego kodu, można za jej pomocą łatwo symulować skomplikowane, zwirtualizowane od- powiedzi danej usługi. WireMock To narzędzie jest podobne do Mountebank. Przy jego użyciu można utworzyć serwer (np. HTTP) o szerokim spektrum wirtualnych odpowiedzi. Narzędzie WireMock napisał w języku Java Tom Akehurst, który cały czas je starannie serwisuje. Stubby4j Jest to narzędzie dla języka Java, bardzo podobne do Mountebank i WireMock. Istnieje już od dłuższego czasu i umożliwia symulowanie skomplikowanych komunikatów SOAP (ang. Simple Object Access Protocol, prosty protokół udostępniania obiektów) i WSDL (ang. Web Services Description Language, język opisu usług WWW) wykorzystywanych przez starsze, zewnętrzne usługi. VCR i Betamax Oba narzędzia są przydatnymi aplikacjami do rejestrowania i odtwarzania ruchu sieciowego. Sprawdzają się szczególnie w sytuacjach, gdy nie ma dostępu do kodu zewnętrznej usługi (a więc kiedy można jedynie obserwować odpowiedzi usługi na odbierane zapytania), gdy usługa zwraca duże ilości danych (które można zarejestrować na zewnętrznym nośniku) albo gdy korzystanie z usługi jest ograniczone lub drogie. Imitacje, atrapy i wirtualizacja usług (cid:95) 161 Poleć książkęKup książkę Hoverfly Jest to nowe narzędzie wirtualizacyjne oferujące więcej opcji konfiguracyjnych niż WireMock czy VCR i umożliwiające symulowanie odpowiedzi wysyłanych przez starsze usługi oraz apli- kacje o skomplikowanych strukturach wzajemnie od siebie zależnych mikrousług. Narzędzia Hoverfly można również używać do przeprowadzania testów obciążeniowych aplikacji wyko- rzystującej zewnętrzną krytyczną usługę, np. SaaS, która w przypadku zwiększonej liczby za- pytań staje się słabym punktem całego systemu. Narzędzie jest napisane w języku Go, co ozna- cza, że jest niewielkie i bardzo wydajne. Uruchomione na niewielkim węźle AWS EC2 może z łatwością obsługiwać tysiące zapytań w ciągu sekundy. Wirtualizacja usług nie jest zbyt popularna wśród programistów, zatem teraz nieco dokładniej opiszemy, jak się ją konfiguruje i z niej korzysta. Wirtualizacja usług za pomocą narzędzia Hoverfly W tym punkcie dowiesz się, jak za pomocą narzędzia Hoverfly wirtualizuje się usługi w lokalnym środowisku programistycznym. Instalacja narzędzia Hoverfly W systemie macOS narzędzie Hoverfly instaluje się za pomocą menedżera pakietów brew. Na stronie http://bit.ly/2Q8dhVC dostępne są wersje tego oprogramowania dla systemów Windows i Linux oraz instrukcje instalacyjne. Możesz również pobrać prostą usługę flights opartą na platformie Spring-Boot i użytą niżej do wyjaśnienia idei wirtualizacji. Rejestrowanie i symulowanie zapytań za pomocą narzędzia Hoverfly Najpierw uruchom narzędzie Hoverfly w sposób pokazany na listingu 8.3. Listing 8.3. Uruchomienie narzędzia Hoverfly $ hoverctl start Hoverfly is now running +------------+------+ | admin-port | 8888 | | proxy-port | 8500 | +------------+------+ W każdej chwili z pomocą polecenia hoverctl status możesz sprawdzić, czy narzędzie działa i jakie porty wykorzystuje (listing 8.4). Listing 8.4. Sprawdzenie stanu narzędzia Hoverfly $ hoverctl status +------------+----------+ | Hoverfly | running | | Admin port | 8888 | | Proxy port | 8500 | | Mode | capture | | Middleware | disabled | +------------+----------+ 162 (cid:95) Rozdział 8. Praca w lokalnym odpowiedniku środowiska produkcyjnego Poleć książkęKup książkę Uruchom teraz usługę flights i wyślij do niej zapytanie, aby sprawdzić, czy działa. W poniższym przykładzie wyszukiwane są wszystkie loty w następnym dniu (pamiętaj, że uzyskany przez Ciebie wynik użycia polecenia curl może być inny niż pokazany w listingu 8.5, ponieważ usługa zwraca losowe dane). Listing 8.5. Uruchomienie przykładowej usługi flights $ ./run-flights-service.sh waiting for service to start waiting for service to start waiting for service to start service started $ curl localhost:8081/api/v1/flights?plusDays=1 | jq [ { origin : Berlin , destination : New York , cost : 617.31 , when : 03:45 }, { origin : Amsterdam , destination : Dubai , cost : 3895.49 , when : 21:20 }, { origin : Milan , destination : New York , cost : 4950.31 , when : 08:49 } ] Teraz przełącz narzędzie Hoverfly w tryb rejestrowania zapytań, tak jak w listingu 8.6. Listing 8.6. Rejestrowanie zapytań za pomocą narzędzia Hoverfly $ hoverctl mode capture Hoverfly has been set to capture mode Wyślij zapytanie do interfejsu usługi flights, ale tym razem użyj narzędzia Hoverfly jako serwera proxy, zgodnie z listingiem 8.7 (pamiętaj, że Twoje wyniki mogą być inne niż tutaj pokazane). Listing 8.7. Rejestrowanie odpowiedzi usługi za pomocą narzędzia Hoverfly $ curl localhost:8081/api/v1/flights?plusDays=1 --proxy localhost:8500 | jq [ { origin : Berlin , destination : Dubai , cost : 3103.56 , when : 20:53 }, { origin : Amsterdam , destination : Boston , Imitacje, atrapy i wirtualizacja usług (cid:95) 163 Poleć książkęKup książkę cost : 2999.69 , when : 19:45 } ] Argument -proxy użyty w powyższym przykładzie powoduje, że zapytanie jest wysyłane do ser- wera proxy (tutaj narzędzia Hoverfly), a następnie do docelowej usługi. Odpowiedź podąża od- wrotną drogą. W ten sposób narzędzie Hoverfly może rejestrować całą komunikację realizowaną poprzez sieć. Zawsze wtedy, gdy nie będziesz wiedział, co się dzieje z narzędziem (czy np. zareje- strowało zapytanie i odpowiedź), możesz sprawdzić dziennik, którego fragment pokazuje listing 8.8. Listing 8.8. Przeglądanie dziennika narzędzia Hoverfly $ hoverctl logs INFO[2019-03-30T08:12:32+01:00] Mode has been changed mode=capture INFO[2019-03-30T08:14:01+01:00] request and response captured mode=capture request= (cid:180) map[headers:map[Accept:[*/*] Proxy-Connection:[Keep-Alive] User-Agent:[curl/7.54.0]] body: (cid:180)method:GET scheme:http destination:localhost:8081 path:/api/v1/flights query:map[plusDays: (cid:180)[1]]] response= map[error:nil response] ... Przyjrzyjmy się teraz utworzonym danym symulacyjnym. Aby to zrobić, należy je wyeksportować i otworzyć w edytorze tekstowym. W listingu 8.9 widoczny jest program atom, ale równie dobrze można użyć innego polecenia (np. vim lub emacs). Listing 8.9. Eksport danych symulacyjnych z narzędzia Hoverfly $ hoverctl export module-two-simulation.json Successfully exported simulation to module-two-simulation.json $ atom module-two-simulation.json Przejrzyj utworzony plik i sprawdź, czy zawiera zarejestrowane dane. Każde zapytanie powinno stanowić osobny element w tabeli. Tak uzyskane dane możesz wykorzystać do symulowania działania usługi. Najpierw zatrzymaj usługę flights i sprawdź, czy nie można już z nią nawiązać komunikacji, tak jak pokazuje listing 8.10. Listing 8.10. Zatrzymanie usługi flights $ ./stop-flights-service.sh service successfully shut down $ curl localhost:8081/api/v1/flights?plusDays=1 curl: (7) Failed to connect to localhost port 8081: Connection refused Przełącz narzędzie Hoverfly w tryb symulacji, zgodnie z listingiem 8.11. Listing 8.11. Przełączenie narzędzia Hoverfly w tryb symulacji $ hoverctl mode simulate Hoverfly has been set to simulate mode with a matching strategy of strongest W tym trybie narzędzie Hoverfly nie przekazuje zapytań do rzeczywistej usługi, tylko odsyła do klienta zarejestrowaną odpowiedź. Ponownie wyślij zapytanie, wskazując jak poprzednio narzę- dzie Hoverfly jako serwer proxy. Tym razem jednak zamiast komunikatu o błędzie powinieneś uzyskać poprawną odpowiedź, tak jak w listingu 8.12. 164 (cid:95) Rozdział 8. Praca w lokalnym odpowiedniku środowiska produkcyjnego Poleć książkęKup książkę Literał 8.12. Wysyłanie zapytań do narzędzia Hoverfly pełniącego rolę serwera proxy $ curl localhost:8081/api/v1/flights?plusDays=1 --proxy localhost:8500 | jq [ { origin : Berlin , destination : Dubai , cost : 3103.56 , when : 20:53 }, { origin : Amsterdam , destination : Boston , cost : 2999.69 , when : 19:45 } ] To wszystko! Udało Ci się zasymulować odwołanie do interfejsu API usługi! W tym przykładzie użyłeś polecenia curl, ale w rzeczywistości zapytania będzie wysłała testowana aplikacja. Jeżeli zapytania i odpowiedzi będą przechowywane w narzędziu Hoverfly, dostęp do oryginalnej usługi nie będzie potrzebny. Ponadto za pomocą tego narzędzia można sterować odpowiedziami. Narzędzie wirtualizacyjne, takie jak Hoverfly, ma m.in. tę zaletę, że w minimalnym stopniu ob- ciąża system i szybko się uruchamia. Za jego pomocą można uruchamiać na laptopie wiele więcej usług wirtualnych niż rzeczywistych w prawdziwym środowisku. Ponadto narzędzie to można wykorzystywać do szybkiego przeprowadzania testów integracyjnych. Nie implementuj na nowo wirtualnej usługi Jeżeli okaże się, że funkcjonalności Twoich wirtualnych usług stopniowo odbiegają od rzeczywistych, możesz odczuwać pokusę, aby zaimplementować w nich bardziej zaawansowane algorytmy lub instrukcje warunkowe. To jest wbrew temu wzorcowi! Choć w ten sposób mógłbyś zaoszczędzić sporo czasu, jednak zdecydowanie nie możesz implementować na nowo wirtualnej wersji usługi. Wirtualizacja idealnie nadaje się do tworzenia inteligentnych imitacji lub atrapy usługi, która ma skom- plikowaną wewnętrzną strukturę, ale zwraca proste dane. Innymi słowy, powinie- neś koncentrować się na wirtualizacji działania, a nie stanu usługi. Jeżeli zaczniesz modyfikować wirtualną usługę, wprowadzając w niej mnóstwo in- strukcji warunkowych określających odpowiedzi, które usługa ma zwracać na od- bierane zapytania, albo gdy wirtualna usługa zacznie przypominać rzeczywistą, to znaczy, że stosujesz antywzorzec i powinieneś zastosować inną technikę. Maszyny wirtualne oraz narzędzia Vagrant i Packer Często podczas wdrażania aplikacji w chmurze będziesz musiał tworzyć obrazy maszyn wirtual- nych zawierających Twoją aplikację Java. W ten sposób będziesz mógł również uruchamiać kilka zależnych od siebie usług (jeżeli będzie ich niewiele, a komputer, którego używasz, będzie odpo- wiednio wydajny). Teraz dowiesz się, jak za pomocą narzędzia HashiCorp Vagrant tworzy się i inicjuje maszyny wirtualne na lokalnym komputerze. Maszyny wirtualne oraz narzędzia Vagrant i Packer (cid:95) 165 Poleć książkęKup książkę Instalacja narzędzia Vagrant Plik instalacyjny narzędzia Vagrant dla systemów macOS, Linux lub Windows można pobrać ze strony https://www.vagrantup.com/downloads.html. Potrzebny Ci również będzie hiperwizor, np. Oracle VirtualBox (https://www.virtualbox.org/wiki/Downloads) lub VMware Fusion (https:// www.vmware.com/uk/products/fusion.html). Utworzenie pliku Vagrantfile W pliku Vagrantfile definiuje się wszystkie maszyny wirtualne tworzące lokalne środowisko pro- gramistyczne. Określa się w nim liczbę maszyn, ilości wykorzystywanych przez nie zasobów oraz ustawienia sieciowe. Dodatkowo można umieszczać skrypty instalujące i konfigurujące wymaga- ne zależności. Listing 8.13 przedstawia przykładowy plik Vagrantfile. Listing 8.13. Plik Vagrantfile tworzący pojedynczą maszynę wirtualną z systemem Ubuntu, instalujący program Jenkins i uruchamiający serwer za pomocą kilku prostych poleceń Bash # -*- mode: ruby -*- # vi: set ft=ruby : # Poniżej znajduje się pełna konfiguracja narzędzia Vagrant. # Argument 2 funkcji Vagrant.configure określa wersję konfiguracji # (zastosowany jest starszy styl w celu zapewnienia wstecznej # kompatybilności). Nie zmieniaj go, chyba że jesteś pewien, co robisz. Vagrant.configure( 2 ) do |config| # Poniżej są opisane najczęściej stosowane opcje konfiguracyjne. # Pełna dokumentacja jest dostępna na stronie https://docs.vagrantup.com. # W każdym środowisku Vagrant potrzebna jest maszyna wirtualna. Lista # dostępnych maszyn znajduje się na stronie https://atlas.hashicorp.com/search. config.vm.box = ubuntu/xenial64 config.vm.box_version = 20170922.0.0 config.vm.network forwarded_port , guest: 8080, host: 8080 config.vm.provider virtualbox do |v| v.memory = 2048 end # Konfiguracja środowiska za pomocą skryptu powłoki. Można stosować narzędzia # konfiguracyjne, np. Puppet, Chef, Ansible, Salt lub Docker. Informacje # na temat składni poleceń i ich użycia znajdują się w dokumentacji. config.vm.provision shell , inline: -SHELL apt-get update # Instalacja komponentów OpenJDK Java JDK i Maven. apt-get install -y openjdk-8-jdk apt-get install -y maven # Instalacja sbt. echo deb https://dl.bintray.com/sbt/debian / | tee -a /etc/apt/sources.list.d/sbt.list apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 2EE0EA64E40A89B84B2DF73499E82A75642AC823 apt-get update apt-get install sbt # Instalacja środowiska Docker (może być bardziej skomplikowana, # jeżeli są potrzebne specyficzne pakiety). apt-get install -y apt-transport-https ca-certificates apt-key adv --keyserver hkp://p80.pool.sks-keyservers.net:80 --recv-keys 58118E89F3A912897C070ADBF76221572C52609D 166 (cid:95) Rozdział 8. Praca w lokalnym odpowiedniku środowiska produkcyjnego Poleć książkęKup książkę echo deb https://apt.dockerproject.org/repo ubuntu-xenial main /etc/apt/sources.list.d/docker.list apt-get update apt-get purge lxc-docker apt-get install -y linux-image-extra-$(uname -r) linux-image-extra-virtual apt-get install -y docker-engine # Instalacja narzędzia Jenkins. wget -q -O - https://pkg.jenkins.io/debian/jenkins-ci.org.key | apt-key add - echo deb http://pkg.jenkins-ci.org/debian binary/ /etc/apt/sources.list.d/jenkins.list apt-get update apt-get install -y jenkins # Wyświetlenie klucza narzędzia Jenkins wymaganego podczas inicjacji. printf \n\nKLUCZ JENKINS\n********************************* # Dodanie użytkownika jenkins do grupy docker. usermod -aG docker jenkins # Oczekiwanie na uruchomienie narzędzia Jenkins i utworzenie # pliku initialAdminPassword. while [ ! -f /var/lib/jenkins/secrets/initialAdminPassword ] do sleep 2 done cat /var/lib/jenkins/secrets/initialAdminPassword printf ********************************* # Ponowne uruchomienie usługi Jenkins w celu zastosowania zmian # wprowadzonych za pomocą polecenia usermod. service jenkins restart # Instalacja Docker Compose. curl -s -L https://github.com/docker/compose/releases/ download/1.10.0/docker-compose-`uname -s`-`uname -m` (cid:1407) /usr/local/bin/docker-compose chmod +x /usr/local/bin/docker-compose SHELL end Maszyny wirtualne zdefiniowane w pliku Vagrantfile uruchamia się za pomocą polecenia vagrant up, tak jak w listingu 8.14, a zatrzymuje i usuwa odpowiednio poleceniami vagrant halt i vagrant destroy. Listing 8.14. Uruchamianie maszyny wirtualnej za pomocą narzędzie Vagrant $ vagrant up Bringing machine default up with virtualbox provider... == default: Checking if box ubuntu/xenial64 is up-to-date... == default: Clearing any previously set forwarded ports... == default: Clearing any previously set network interfaces... == default: Preparing network interfaces based on configuration... default: Adapter 1: nat == default: Forwarding ports... default: 8080 (guest) = 8080 (host) (adapter 1) default: 22 (guest) = 2222 (host) (adapter 1) == default: Running pre-boot VM customizations... Maszyny wirtualne oraz narzędzia Vagrant i Packer (cid:95) 167 Poleć książkęKup książkę == default: Booting VM... == default: Waiting for machine to boot. This may take a few minutes... default: SSH address: 127.0.0.1:2222 default: SSH username: ubuntu default: SSH auth method: password == default: Machine booted and ready! Jeżeli przyjrzysz się plikowi Vagrantfile przedstawionemu w listingu 8.13, zauważysz wiersz config.vm.network forwarded_port , guest: 8080, host: 8080 wiążący port nr 8080 wy- korzystywany przez maszynę wirtualną z portem o takim samym numerze używanym przez lo- kalny system operacyjny. Oznacza to, że po wpisaniu w przeglądarce adresu http://localhost:8080 pojawi się strona narzędzia Jenkins uruchomionego na maszynie utworzonej za pomocą narzę- dzia Vagrant. Jak pamiętasz z podrozdziału „Tworzenie obrazów maszyn dla wielu chmur za pomocą programu Packer”, możesz utworzyć za pomocą wymienionego narzędzia obrazy maszyn, które następnie zainicjujesz przy użyciu opcji konfiguracyjnej config.vm.box w pliku Vagrantfile. Wzorzec 3.: pudełkowe środowisko produkcyjne Za pomocą narzędzia wirtualizacyjnego, takiego jak HashiCorp Vagrant, można łatwo uruchamiać na lokalnym komputerze pobrane z internetu obrazy maszyn wirtualnych, zawierające gotowe usługi i wykorzystywać je do tworzenia aplikacji i uruchamiania automatycznych testów. W ten sposób można też utworzyć tzw. pudełkowe środowisko produkcyjne, czyli prostszą wersję rze- czywistego środowiska, którą można udostępnić innym członkom zespołu i zapewniać w ten spo- sób spójną współpracę. W tym celu należy utworzyć obraz maszyny zawierającej system opera- cyjny, kod źródłowy i pliki binarne aplikacji, jej konfigurację oraz niezbędne magazyny danych. Czy tworzenie pudełkowego środowiska produkcyjnego jest antywzorcem Pudełkowe środowisko produkcyjne najbardziej przydaje się w zespołach korzy- stających z niewielkiego, stabilnego środowiska produkcyjnego, w którym urucho- mionych jest niewiele usług. Gdy jednak aplikacja zacznie się powiększać, będzie korzystać z więcej niż pięciu usług lub ich struktura i konfiguracja zaczną się kom- plikować, wtedy lokalne replikowanie środowiska produkcyjnego stanie się nieprak- tyczne, a utrzymywanie spójności obu środowisk będzie zajmowało dużo czasu. Gdy zauważysz, że lokalna replika nie odzwierciedla działania rzeczywistego środo- wiska lub zbyt wiele wysiłku i czasu wymaga utrzymywanie repliki, będzie to znak, że wzorzec stał się antywzorcem. Wraz z pojawieniem się narzędzia HashiCorp Packer proces tworzenia obrazów maszyn wirtual- nych stał się jeszcze prostszy. Za pomocą tego narzędzia można określać parametry obrazu i sto- sować je do tworzenia różnych środowisk (np. produkcyjnego w chmurze Azure, testowego w OpenStack i programistycznego na lokalnym komputerze). Niewątpliwie do popularności tego stylu pakowania aplikacji przyczyniła się platforma Docker (opisana dalej w tym rozdziale) z na- rzędziem Fig niczym wisienką na torcie. Z czasem narzędzie to przekształciło się w Docker Compose 168 (cid:95) Rozdział 8. Praca w lokalnym odpowiedniku środowiska produkcyjnego Poleć książkęKup książkę i obecnie umożliwia tworzenie deklaratywnych specyfikacji aplikacji i usług, związanych z nimi zależności oraz magazynów danych. Opisany tu wzorzec pozwala w elastyczny sposób uruchamiać na lokalnym komputerze zestaw uzależnionych od siebie usług, a jedynym ograniczeniem są za- soby sprzętowe (szczególnie w przypadku korzystania z platform wirtualizacyjnych). Stosując wzorzec pudełkowy, można tworzyć znacznie prostsze lokalne środowiska programi- styczne i unikać potencjalnych konfliktów konfiguracyjnych (spowodowanych np. różnymi wer- sjami języka Java), ponieważ skonfigurowane usługi wraz z zależnościami stanowią jedną całość. Obrazy można parametryzować (za pomocą opcji inicjacyjnych i zmiennych środowiskowych) i tworzyć profile, dzięki czemu usługi mogą działać zgodnie z oczekiwaniami. Wtyczki Docker dla narzędzia Maven pozwalają integrować kontenery z procedurami testowymi. Potencjalnie opisa- ny wzorzec można rozszerzyć o rozwijanie kodu samych obrazów, np. poprzez zamontowanie lo- kalnego kodu źródłowego w uruchomionej instancji obrazu. Jeżeli zrobi się to umiejętnie, można praktycznie zrezygnować z instalowania na lokalnym komputerze jakichkolwiek narzędzi (oprócz ulubionego środowiska IDE), co znacznie upraszcza cały proces tworzenia aplikacji. Programowanie chmurowe (z dużym pudełkowym środowiskiem produkcyjnym)? Na rynku pojawiają się chmurowe środowiska IDE, np. Eclipse Che i Amazon Cloud9. Część anality- ków uważa, że przyszłością programowania są narzędzia instalowane w chmurze, a nie na lokalnym komputerze. Czas pokaże, czy to prawda. Sam jednak wielokrotnie przekonasz się, że środowiska chmurowe umożliwiają uruchamianie repliki środowiska produkcyjnego (lub jego części) i dołączanie go do „lokalnego” chmurowego środowiska IDE, jak to ma miejsce w przypadku bezserwerowych aplikacji FaaS. Niezależnie od tego, czy zamierzasz używać takiego lokalnego środowiska, czy nie, warto, abyś poznał ten wzorzec i przyszłościowe metody programowania. Kontenery: Kubernetes, minikube i Telepresence W tym podrozdziale dowiesz się, jak lokalnie korzystać z kontenerów Docker i platformy instru- mentacyjnej Kubernetes. Przykładowa aplikacja Docker Java Shop Do uruchamiania kontenerów na produkcyjną skalę potrzebna jest platforma instrumentacyjna i planistyczna. Istnieje kilka takich platform, m.in. Docker Swarm, Apache Mesos i AWS ECS, ale najpopularniejszą jest Kubernetes (https://kubernetes.io), stosowana w wielu środowiskach pro- dukcyjnych. Obecnie platformę tę rozwija fundacja CNCF (ang. Cloud Native Computing Foun- dation, https://www.cncf.io). Poniżej opisany jest przykład wykorzystania jej do uruchomienia w kontenerach Docker aplikacji Java obsługującej sklep internetowy. Rysunek 8.1 przedstawia architekturę aplikacji Docker Java Shopfront, którą umieścimy w konte- nerach i wdrożymy za pomocą platformy Kubernetes. Kontenery: Kubernetes, minikube i Telepresence (cid:95) 169 Poleć książkęKup książkę Rysunek 8.1. Architektura aplikacji Docker Java Shopfront Tworzenie aplikacji Java i obrazów kontenerów Zanim utworzysz kontener i odpowiedni plik konfiguracyjny dla platformy Kubernetes, musisz wykonać następujące operacje. Zainstalować środowisko Docker w systemie macOS (https://dockr.ly/2zwBIqz), Windows (https://dockr.ly/2NL7dWn) lub Linux (https://dockr.ly/2xUSIV5) Środowisko to służy do tworzenia, uruchamiania i testowania kontenerów Docker na lokal- nym komputerze niezależnie od platformy Kubernetes. Zainstalować narzędzie minikube (http://bit.ly/2xNk8w4) Jest to narzędzie ułatwiające uruchamianie jednowęzłowego klastra kontenerów jako maszyny wirtualnej na lokalnym komputerze. Utworzyć konto w serwisie GitHub (https://github.com) i zainstalować program Git (https://git-scm.com) Przykładowe kody są zapisane w serwisie GitHub, a za pomocą narzędzia Git można tworzyć odgałęzienia repozytorium i zatwierdzać zmiany wprowadzane w lokalnej kopii aplikacji. Utworzyć konto w serwisie Docker Hub (https://hub.docker.com) Jeżeli zamierzasz postępować zgodnie z podanymi niżej wskazówkami, będziesz potrzebować konta w serwisie Docker Hub, aby w nim zapisywać kopie utworzonych obrazów. Zainstalować pakiet Java SDK w wersji 8. lub 9. (http://bit.ly/2xO16pw) i narzędzie Maven (https://maven.apache.org) W kodzie wykorzystasz funkcjonalności języka Java 8. Skompilujesz go wraz z zależnościami za pomocą narzędzia Maven. 170 (cid:95) Rozdział 8. Praca w lokalnym odpowiedniku środowiska produkcyjnego Poleć książkęKup książkę Sklonuj repozytorium zapisane w serwisie GitHub (ewentualnie utwórz odgałęzienie repozyto- rium i jego lokalną kopię) zgodnie z listingiem 8.15. Następnie odszukaj aplikację mikrousługową Shopfront (http://bit.ly/2Og0JOP). Listing 8.15. Klonowanie przykładowego repozytorium $ git clone git@github.com:danielbryantuk/oreilly-docker-java-shopping.git $ cd oreilly-docker-java-shopping/shopfront W swoim ulubionym środowisku, np. IntelliJ IDEA lub Eclipse, otwórz kod aplikacji, przejrzyj go i skompiluj za pomocą narzędzia Maven, zgodnie z listingiem 8.16. Wykonywalny plik JAR apli- kacji zostanie utworzony w katalogu ./target. Listing 8.16. Kompilowanie aplikacji Spring Boot $ mvn clean install ... [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------ [INFO] Total time: 15.140 s [INFO] Finished at: 2019-03-30T18:01:49+01:00 [INFO] Final Memory: 41M/328M [INFO] ------------------------------------------------------------------------ Teraz utwórz obraz kontenera Docker. Dane systemu operacyjnego, konfigurację i instrukcje tworzące obraz zazwyczaj umieszcza się w pliku Dockerfile. Listing 8.17 przedstawia przykładowy plik zapisany w katalogu shopfront. Listing 8.17. Przykładowy plik Dockerfile dla aplikacji Spring Boot Java FROM openjdk:8-jre ADD target/shopfront-0.0.1-SNAPSHOT.jar app.jar EXPOSE 8010 ENTRYPOINT [ java , -Djava.security.egd=file:/dev/./urandom , -jar , /app.jar ] Pierwszy wiersz zawiera informację, że obraz zostanie utworzony na podstawie obrazu bazowego openjdk:8-jre. Obraz ten (dostępny na stronie https://hub.docker.com/_/openjdk) jest utrzy- mywany przez zespół OpenJDK i zawiera wszystko, co jest potrzebne do uruchamiania w konte- nerze Docker aplikacji napisanych w języku Java 8 (m.in. system operacyjny i skonfigurowane środowisko OpenJDK 8 JRE). Drugi wiersz zawiera instrukcję odczytującą plik JAR i umieszcza- jącą go w obrazie. W trzecim wierszu wskazany jest port nr 8010 wykorzystywany przez aplikację. Port ten musi być dostępny z zewnątrz kontenera. Czwarty wiersz zawiera punkt wejścia do apli- kacji lub polecenie wykonywane podczas inicjacji kontenera. Listing 8.18 przedstawia proces two- rzenia kontenera. Listing 8.18. Proces tworzenia kontenera Docker $ docker build -t danielbryantuk/djshopfront:1.0 . Successfully built 87b8c5aa5260 Successfully tagged danielbryantuk/djshopfront:1.0 Utworzony obraz umieść w serwisie Docker Hub zgodnie z listingiem 8.19. Wcześniej, za pomocą wiersza poleceń musisz zalogować się do serwisu, używając swojego loginu i hasła. Kontenery: Kubernetes, minikube i Telepresence (cid:95) 171 Poleć książkęKup książkę Listing 8.19. Wysłanie obrazu do serwisu Docker Hub $ docker login Login with your Docker ID to push and pull images from Docker Hub. If you don t have a Docker ID, head over to https://hub.docker.com to create one. Username: Password: Login Succeeded $ $ docker push danielbryantuk/djshopfront:1.0 The push refers to a repository [docker.io/danielbryantuk/djshopfront] 9b19f75e8748: Pushed ... cf4ecb492384: Pushed 1.0: digest: sha256:8a6b459b0210409e67bee29d25bb512344045bd84a262ede80777edfcff3d9a0 size: 2210 Wdrożenie kontenera na platformie Kubernetes Teraz uruchom kontener na platformie Kubernetes. Najpierw przejdź do głównego katalogu projektu kubernetes. $ cd ../kubernetes Otwórz plik wdrożeniowy shopfront-service.yaml. Listing 8.20 przedstawia przykładową zawar- tość tego pliku. Listing 8.20. Plik wdrożeniowy shopfront-service.yaml usługi Shopfront --- apiVersion: v1 kind: Service metadata: name: shopfront labels: app: shopfront spec: type: ClusterIP selector: app: shopfront ports: - protocol: TCP port: 8010 name: http --- apiVersion: apps/v1beta2 kind: Deployment metadata: name: shopfront labels: app: shopfront spec: replicas: 1 selector: matchLabels: app: shopfront template: metadata: 172 (cid:95) Rozdział 8. Praca w lokalnym odpowiedniku środowiska produkcyjnego Poleć książkęKup książkę labels: app: shopfront spec: containers: - name: djshopfront image: danielbryantuk/djshopfront:1.0 ports: - containerPort: 8010 livenessProbe: httpGet: path: /health port: 8010 initialDelaySeconds: 30 timeoutSeconds: 1 W pierwszej sekcji pliku tworzona jest usługa shopfront, która będzie kierowała wysyłane do portu 8010 pakiety TCP do kontenera z etykietą app: shopfront. W drugiej sekcji tworzone jest środowisko, w którym będzie uruchomiona jedna replika (instancja) kontenera zdefiniowanego w pierwszej sekcji pliku. Oprócz tego otwierany jest tu port 8010 wykorzystywany przez kontener Docker oraz deklarowane są identyfikatory livenessProbe i healthcheck, niezbędne dla platformy Kubernetes do sprawdzania, czy aplikacja działa poprawnie i może przetwarzać odbierane pakiety. Wpisz teraz polecenie minikube, tak jak na listingu 8.21, aby zainstalować usługę (zwróć uwagę, że w zależności od zasobów dostępnych na Twoim komputerze może być konieczna zmiana para- metrów określających liczbę procesorów i wielkość pamięci). Listing 8.21. Instalacja usługi za pomocą polecenia minikube $ minikube start --cpus 2 --memory 4096 Starting local Kubernetes v1.7.5 cluster... Starting VM... Getting VM IP address... Moving files into cluster... Setting up certs... Connecting to cluster... Setting up kubeconfig... Starting cluster components... Kubectl is now configured to use the cluster. $ kubectl apply -f shopfront-service.yaml service shopfront created deployment shopfront created Listę wszystkich usług uruchomionych na platformie Kubernetes możesz w każdej chwili wy- świetlić za pomocą polecenia kubectl get svc, tak jak na listingu 8.22. Listing 8.22. Polecenie kubectl get svc $ kubectl get svc NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes 10.0.0.1 none 443/TCP 18h shopfront 10.0.0.216 nodes 8010:31208/TCP 12s $ kubectl get pods NAME READY STATUS RESTARTS AGE shopfront-0w1js 0/1 ContainerCreating 0 18s $ kubectl get pods NAME READY STATUS RESTARTS AGE shopfront-0w1js 1/1 Running 0 2m Wdrożyłeś na platformie Kubernetes swoją pierwszą usługę! Kontenery: Kubernetes, minikube i Telepresence (cid:95) 173 Poleć książkęKup książkę Prosty test usługi Za pomocą polecenia curl użytego ze ścieżką health, tak jak na listingu 8.23, możesz pobrać dane z usługi. W ten prosty sposób możesz sprawdzić, czy wszystko działa zgodnie z oczekiwaniami. Listing 8.23. Prosty test usługi $ curl $(minikube service shopfront --url)/health { status : UP } Wynik zwrócony przez polecenie curl użyte ze ścieżką /health potwierdza, że usługa działa po- prawnie. Jednak do pełnego uruchomienia aplikacji niezbędne jest wdrożenie pozostałych konte- nerów z mikrousługami. Utworzenie pozostałych usług Teraz, gdy główny kontener działa prawidłowo, utwórz zgodnie z listingiem 8.24 pozostałe dwa kontenery z dodatkowymi mikrousługami. Listing 8.24. Utworzenie pozostałych usług $ cd .. $ cd productcatalogue/ $ mvn clean install … $ docker build -t danielbryantuk/djproductcatalogue:1.0 . ... $ docker push danielbryantuk/djproductcatalogue:1.0 ... $ cd .. $ cd stockmanager/ $ mvn clean install ... $ docker build -t danielbryantuk/djstockmanager:1.0 . ... $ docker push danielbryantuk/djstockmanager:1.0 Utworzyłeś i zapisałeś w serwisie Docker Hub wszystkie mikrousługi i obrazy kontenerów. Pora wdrożyć usługi productcatalogue i stockmanager na platformie Kubernetes. Wdrożenie całej usługi Java na platformie Kubernetes W sposób podobny do poprzedniego musisz wdrożyć na platformie Kubernetes dwie pozostałe usługi (listing 8.25). Listing 8.25. Wdrożenie całej aplikacji Java na platformie Kubernetes $ cd .. $ cd kubernetes/ $ kubectl apply -f productcatalogue-service.yaml service productcatalogue created deployment productcatalogue created 174 (cid:95) Rozdział 8. Praca w lokalnym odpowiedniku środowiska produkcyjnego Poleć książkęKup książkę $ kubectl apply -f stockmanager-service.yaml service stockmanager created deployment stockmanager created $ kubectl get svc NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes 10.0.0.1 none 443/TCP 19h productcatalogue 10.0.0.37 nodes 8020:31803/TCP 42s shopfront 10.0.0.216 nodes 8010:31208/TCP 13m stockmanager 10.0.0.149 nodes 8030:30723/TCP 16s $ kubectl get pods NAME READY STATUS RESTARTS AGE productcatalogue-79qn4 1/1 Running 0 55s shopfront-0w1js 1/1 Running 0 13m stockmanager-lmgj9 1/1 Running 0 29s Jeżeli zbyt wcześnie wpiszesz polecenie kubectl get pods, może się okazać, że nie wszystkie kontenery zostały uruchomione. Zanim przejdziesz do następnego punktu, zaczekaj, aż wszystkie usługi zaczną działać (jest to dobry moment, aby napić się kawy!). Kontrola wdrożonej aplikacji Po wdrożeniu wszystkich usług i uruchomieniu kontenerów powinieneś uzyskać dostęp do in- terfejsu graficznego aplikacji. Kiedy wpiszesz poniższe polecenie minikube, powinna się otworzyć w przeglądarce strona pokazana na rysunku 8.2. $ minikube service shopfront Rysunek 8.2. Prosty interfejs graficzny aplikacji Shopfront uruchomionej w kontenerze Docker Platformę Kubernetes można uruchamiać nie tylko lokalnie, ale również na zewnętrznym klastrze serwerów. Aplikację można wtedy rozwijać za pomocą narzędzia Datawire Telepresence. Przyj- rzyjmy się teraz temu rozwiązaniu. Kontenery: Kubernetes, minikube i Telepresence (cid:95) 175 Poleć książkęKup książkę Telepresence: praca zdalna i lokalna Telepresence jest to bezpłatne narzędzie umożliwiające uruchamianie na lokalnym komputerze usługi, która komunikuje się z zewnętrznym klastrem serwerów uruchomionych na platformie Kubernetes. Dzięki temu programista tworzący aplikację opartą na mikrousługach może: (cid:120) szybko tworzyć jedną usługę na lokalnym komputerze, nawet jeżeli jest ona uzależniona od usług działających w klastrze, a po wprowadzeniu i zapisaniu zmian natychmiast zobaczyć swoją usługę w działaniu, (cid:120) testować, diagnozować i edytować usługę z
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Ciągłe dostarczanie oprogramowania w języku Java. Najlepsze narzędzia i praktyki wdrażania kodu
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ą: