Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00198 005837 19007051 na godz. na dobę w sumie
Rozwijanie mikrousług w Pythonie. Budowa, testowanie, instalacja i skalowanie - książka
Rozwijanie mikrousług w Pythonie. Budowa, testowanie, instalacja i skalowanie - książka
Autor: Liczba stron: 280
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-283-4596-6 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> programowanie >> python - programowanie
Porównaj ceny (książka, ebook (-35%), audiobook).

Rozwijanie mikrousług w Pythonie. Budowa, testowanie, instalacja i skalowanie

Mikrousługi są bardzo ciekawym trendem tworzenia kodu. Pojawił się on kilka lat temu z uwagi na potrzebę przyspieszenia cyklu udostępniania oprogramowania. Nowe produkty i funkcje musiały być oferowane użytkownikom możliwie najszybciej. Wkrótce okazało się, że tworzenie architektury aplikacji składającej się z małych, funkcjonalnych jednostek - właśnie mikrousług - jest bardzo obiecującym sposobem pracy. Pozwala na zwiększenie się elastyczności oraz szybkości wprowadzania innowacji, gdyż programista może zająć się jednym elementem bez zastanawiania się nad całością aplikacji. W świecie, w którym rządzą wydajność i krótki czas dostarczania kodu, jest to duża wartość!

Dzięki tej książce dowiesz się, w jaki sposób niewielkie, standardowe elementy kodu mogą złożyć się na kompletną, działającą aplikację. Nauczysz się tworzyć takie mikrousługi, rozwiązywać pojawiające się problemy i nabierzesz nawyku stosowania dobrych praktyk. Szybko zaczniesz pisać aplikacje w Pythonie za pomocą szerokiego wachlarza dostępnych narzędzi, włączając w to Flask czy Tox. Przy okazji nauczysz się zasad programowania zorientowanego na testy. Dowiesz się, jak zabezpieczać komunikację pomiędzy usługami i kodować funkcjonalności zapory aplikacyjnej w języku Lua dla serwera Nginx. Poznasz też możliwości instalowania mikrousług w chmurze AWS z wykorzystaniem kontenerów Docker.

W tej książce między innymi:

Mikrousługi w języku Python: integracja doskonała!

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

Darmowy fragment publikacji:

Tytuł oryginału: Python Microservices Development Tłumaczenie: Andrzej Watrak ISBN: 978-83-283-4596-6 Copyright © Packt Publishing 2017. First published in the English language under the title ‘Python Microservices Development – (9781785881114)’ Polish edition copyright © 2018 by Helion SA All rights reserved. All rights reserved. No part of this book may be reproduced or transmitted in any form or by any means, electronic or mechanical, including photocopying, recording or by any information storage retrieval system, without permission from the Publisher. Wszelkie prawa zastrzeżone. Nieautoryzowane rozpowszechnianie całości lub fragmentu niniejszej publikacji w jakiejkolwiek postaci jest zabronione. Wykonywanie kopii metodą kserograficzną, fotograficzną, a także kopiowanie książki na nośniku filmowym, magnetycznym lub innym powoduje naruszenie praw autorskich niniejszej publikacji. Wszystkie znaki występujące w tekście są zastrzeżonymi znakami firmowymi bądź towarowymi ich właścicieli. Autor oraz Helion SA dołożyli wszelkich starań, by zawarte w tej książce informacje były kompletne i rzetelne. Nie biorą jednak żadnej odpowiedzialności ani za ich wykorzystanie, ani za związane z tym ewentualne naruszenie praw patentowych lub autorskich. Autor oraz Helion SA nie ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji zawartych w książce. Helion SA ul. Kościuszki 1c, 44-100 Gliwice tel. 32 231 22 19, 32 230 98 63 e-mail: helion@helion.pl WWW: http://helion.pl (księgarnia internetowa, katalog książek) Drogi Czytelniku! Jeżeli chcesz ocenić tę książkę, zajrzyj pod adres http://helion.pl/user/opinie/rozmik 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/rozmik.zip Printed in Poland. • Kup książkę • Poleć książkę • Oceń książkę • Księgarnia internetowa • Lubię to! » Nasza społeczność Spis tre(cid:258)ci O autorze O korektorze merytorycznym Przedmowa Wst(cid:218)p Rozdzia(cid:239) 1. Czym s(cid:200) mikrous(cid:239)ugi? Geneza architektury SOA Podej(cid:258)cie monolityczne Podej(cid:258)cie mikrous(cid:239)ugowe Zalety mikrous(cid:239)ug Rozdzielenie zakresów odpowiedzialno(cid:258)ci Mniejsze projekty Skalowanie i wdra(cid:285)anie Wady mikrous(cid:239)ug Nielogiczny podzia(cid:239) aplikacji Wi(cid:218)cej interakcji sieciowych Powielanie danych Problemy z kompatybilno(cid:258)ci(cid:200) Skomplikowane testy Implementacja mikrous(cid:239)ug w j(cid:218)zyku Python Standard WSGI Biblioteki Greenlet i Gevent Platformy Twisted i Tornado Modu(cid:239) asyncio Wydajno(cid:258)(cid:202) kodu Podsumowanie 9 10 11 15 17 18 19 22 24 24 24 25 26 26 27 27 28 28 29 29 31 33 34 36 38 Poleć książkęKup książkę Spis tre(cid:286)ci Rozdzia(cid:239) 2. Platforma Flask Jaka wersja Pythona? Obs(cid:239)uga zapyta(cid:241) w platformie Flask Kierowanie zapyta(cid:241) Zapytanie Odpowied(cid:283) Wbudowane funkcjonalno(cid:258)ci platformy Flask Obiekt session Zmienne globalne Sygna(cid:239)y Rozszerzenia i po(cid:258)redniki Szablony Konfiguracja Konspekty Obs(cid:239)uga b(cid:239)(cid:218)dów i diagnostyka kodu Szkielet mikrous(cid:239)ugi Podsumowanie Rozdzia(cid:239) 3. Cykl doskona(cid:239)y: kodowanie, testowanie, dokumentowanie Rodzaje testów Testy jednostkowe Testy funkcjonalne Testy integracyjne Testy obci(cid:200)(cid:285)eniowe Testy ca(cid:239)o(cid:258)ciowe Pakiet WebTest Narz(cid:218)dzia pytest i tox Dokumentacja programistyczna Ci(cid:200)g(cid:239)a integracja System Travis CI System ReadTheDocs System Coveralls Podsumowanie Rozdzia(cid:239) 4. Aplikacja Runnerly Aplikacja Runnerly Historie u(cid:285)ytkowników Struktura monolityczna Model Widok i szablon Zadania wykonywane w tle aplikacji Uwierzytelnianie i autoryzowanie u(cid:285)ytkowników Zebranie elementów w monolityczn(cid:200) ca(cid:239)o(cid:258)(cid:202) Dzielenie monolitu Us(cid:239)uga danych Standard Open API 2.0 Dalszy podzia(cid:239) aplikacji Podsumowanie 4 39 40 41 44 47 49 50 51 51 52 53 55 56 58 59 62 64 65 67 67 70 72 72 75 76 78 80 84 85 86 86 88 89 89 90 91 92 93 96 99 102 104 105 106 108 110 Poleć książkęKup książkę Spis tre(cid:286)ci Rozdzia(cid:239) 5. Interakcje z innymi us(cid:239)ugami Wywo(cid:239)ania synchroniczne Sesje w aplikacji Flask Pula po(cid:239)(cid:200)cze(cid:241) Pami(cid:218)(cid:202) podr(cid:218)czna i nag(cid:239)ówki HTTP Przyspieszanie przesy(cid:239)ania danych Wnioski Wywo(cid:239)ania asynchroniczne Kolejki zada(cid:241) Kolejki tematyczne Publikowanie i subskrybowanie komunikatów Wywo(cid:239)ania RPC w protokole AMQP Wnioski Testy Imitowanie wywo(cid:239)a(cid:241) synchronicznych Imitowanie wywo(cid:239)a(cid:241) asynchronicznych Podsumowanie Rozdzia(cid:239) 6. Monitorowanie us(cid:239)ug Centralizacja dzienników Konfiguracja systemu Graylog Wysy(cid:239)anie logów do systemu Graylog Dodatkowe pola Wska(cid:283)niki wydajno(cid:258)ciowe Wska(cid:283)niki systemowe Wska(cid:283)niki wydajno(cid:258)ciowe kodu Wska(cid:283)niki wydajno(cid:258)ciowe serwera WWW Podsumowanie Rozdzia(cid:239) 7. Zabezpieczanie us(cid:239)ug Protokó(cid:239) OAuth2 Uwierzytelnienie oparte na tokenach Standard JWT Biblioteka PyJWT Uwierzytelnianie za pomoc(cid:200) certyfikatu X.509 Mikrous(cid:239)uga TokenDealer Stosowanie us(cid:239)ugi TokenDealer Zapora WAF Platforma OpenResty: serwer Nginx i j(cid:218)zyk Lua Zabezpieczanie kodu Sprawdzanie odbieranych zapyta(cid:241) Ograniczanie zakresu dzia(cid:239)ania aplikacji Analizator Bandit Podsumowanie 111 112 113 116 117 120 124 125 125 126 130 130 131 131 131 133 135 137 138 139 142 145 146 146 148 150 151 153 154 156 156 158 160 162 165 167 169 174 175 178 179 181 5 Poleć książkęKup książkę Spis tre(cid:286)ci Rozdzia(cid:239) 8. Wszystko razem Tworzenie interfejsu za pomoc(cid:200) biblioteki ReactJS J(cid:218)zyk JSX Komponenty ReactJS Biblioteka ReactJS i platforma Flask Bower, npm i Babel Wspó(cid:239)dzielenie zasobów mi(cid:218)dzy domenami Uwierzytelnianie u(cid:285)ytkowników i autoryzowanie zapyta(cid:241) Komunikacja z us(cid:239)ug(cid:200) danych Uzyskiwanie tokena Strava Uwierzytelnienie w kodzie JavaScript Podsumowanie Rozdzia(cid:239) 9. Spakowanie i uruchomienie Runnerly Narz(cid:218)dzia pakuj(cid:200)ce Kilka definicji Pakowanie projektów Wersje projektu Udost(cid:218)pnianie projektu Rozpowszechnianie projektu Uruchamianie mikrous(cid:239)ug Zarz(cid:200)dzanie procesami Podsumowanie Rozdzia(cid:239) 10. Us(cid:239)ugi kontenerowe Czym jest Docker? Docker od podstaw Uruchamianie aplikacji Flask na platformie Docker Kompletny system — OpenResty, Circus i Flask Platforma OpenResty Mened(cid:285)er Circus Wdro(cid:285)enia kontenerowe Docker Compose Klastrowanie i prowizjonowanie kontenerów Podsumowanie Rozdzia(cid:239) 11. Instalacja w chmurze AWS Chmura AWS Kierowanie zapyta(cid:241) — Route53, ELB i AutoScaling Wykonywanie kodu — EC2 i Lambda Gromadzenie danych — EBS, S3, RDS, ElasticCache i CloudFront Powiadamianie — SES, SQS i SNS Prowizjonowanie i uruchamianie — CloudFormation i ECS 6 183 184 185 186 189 190 193 195 195 196 198 199 201 202 203 204 211 213 215 218 220 223 225 226 227 229 231 232 233 236 237 239 241 243 244 245 246 247 248 250 Poleć książkęKup książkę Spis tre(cid:286)ci Podstawy wdra(cid:285)ania mikrous(cid:239)ug w chmurze AWS Utworzenie konta w chmurze AWS Instalowanie instancji EC2 z systemem CoreOS Wdra(cid:285)anie klastrów przy u(cid:285)yciu us(cid:239)ugi ECS Us(cid:239)uga Route53 Podsumowanie Rozdzia(cid:239) 12. Co dalej? Iteratory i generatory Koprocedury Biblioteka asyncio Platforma aiohttp Platforma Sanic Model asynchroniczny i synchroniczny Podsumowanie Skorowidz 250 251 253 257 262 263 265 266 269 270 271 272 273 275 276 7 Poleć książkęKup książkę Poleć książkęKup książkę 1 Czym s(cid:200) mikrous(cid:239)ugi? Od zawsze starali(cid:258)my si(cid:218) usprawnia(cid:202) proces tworzenia oprogramowania, a od czasów kart perforowanych usprawnienia te — mówi(cid:200)c ogl(cid:218)dnie — s(cid:200) ogromne. Jednym z takich usprawnie(cid:241) jest trend mikrous(cid:239)ug, który pojawi(cid:239) si(cid:218) kilka lat temu. Jego (cid:283)ród(cid:239)em by(cid:239)a mi(cid:218)dzy innymi potrzeba przyspieszenia cyklu udost(cid:218)pniania oprogramowania w firmach informatycznych. Nowe produkty i funkcje musia(cid:239)y by(cid:202) oferowane u(cid:285)ytkownikom mo(cid:285)liwie jak najszybciej. Kolejne wersje mia(cid:239)y powstawa(cid:202) cz(cid:218)sto, aby mo(cid:285)na je by(cid:239)o sprzedawa(cid:202), sprze- dawa(cid:202) i jeszcze raz sprzedawa(cid:202). W przypadku us(cid:239)ugi, z której korzystaj(cid:200) tysi(cid:200)ce, a nawet miliony u(cid:285)ytkowników, dobr(cid:200) prak- tyk(cid:200) okaza(cid:239)o si(cid:218) udost(cid:218)pnianie im eksperymentalnej funkcjonalno(cid:258)ci i wycofywanie jej, je(cid:285)eli nie dzia(cid:239)a(cid:239)a poprawnie, zamiast cyzelowania jej miesi(cid:200)cami przed udost(cid:218)pnieniem. Firmy takie jak Netflix promuj(cid:200) techniki ci(cid:200)g(cid:239)ego dostarczania oprogramowania, polegaj(cid:200)ce na cz(cid:218)stym wprowadzaniu ma(cid:239)ych zmian w (cid:258)rodowisku produkcyjnym i testowaniu ich na wybranej grupie u(cid:285)ytkowników. W ten sposób powsta(cid:239)o narz(cid:218)dzie Spinnaker (http://www.spinnaker.io) automatyzuj(cid:200)ce proces aktualizacji oprogramowania i udost(cid:218)pniania funkcjonalno(cid:258)ci w chmurze w postaci niezale(cid:285)nych mikrous(cid:239)ug. Je(cid:285)eli korzystasz z serwisów Hacker News lub Reddit, na pewno trudno Ci jest oceni(cid:202), które informacje mog(cid:200) by(cid:202) dla Ciebie wa(cid:285)ne, a które s(cid:200) tylko medialnym szumem. Napisz artyku(cid:239) obiecuj(cid:200)cy zbawienie, uczy(cid:241) go czym(cid:258) uporz(cid:200)dkowanym, wirtualnym, abstrakcyjnym i niejasnym na wy(cid:285)szym poziomie, i mo(cid:285)esz prawie by(cid:202) pewnym, (cid:285)e roz- poczniesz w ten sposób nowy kult. — Edsger W. Dijkstra Poleć książkęKup książkę Rozwijanie mikrous(cid:225)ug w Pythonie Celem tego rozdzia(cid:239)u jest wyja(cid:258)nienie, czym s(cid:200) mikrous(cid:239)ugi. Skupimy si(cid:218) w nim na ró(cid:285)nych sposobach tworzenia mikrous(cid:239)ug w j(cid:218)zyku Python. Rozdzia(cid:239) sk(cid:239)ada si(cid:218) z nast(cid:218)puj(cid:200)cych cz(cid:218)(cid:258)ci: (cid:81) Wprowadzenie do architektury SOA (cid:81) Metodyka tworzenia aplikacji monolitycznych (cid:81) Metodyka tworzenia aplikacji opartych na mikrous(cid:239)ugach (cid:81) Zalety mikrous(cid:239)ug (cid:81) Wady mikrous(cid:239)ug (cid:81) Kodowanie mikrous(cid:239)ug w j(cid:218)zyku Python Po przeczytaniu tego rozdzia(cid:239)u b(cid:218)dziesz dok(cid:239)adnie wiedzia(cid:239), czym s(cid:200), a czym nie s(cid:200) mikro- us(cid:239)ugi, i b(cid:218)dziesz gotów na poznanie zawi(cid:239)o(cid:258)ci ich tworzenia. Dowiesz si(cid:218) równie(cid:285), jak u(cid:285)y- wa(cid:202) j(cid:218)zyka Python. Geneza architektury SOA Nie istnieje oficjalny standard mikrous(cid:239)ug, dlatego funkcjonuje kilka ich definicji. Cz(cid:218)sto przy próbie okre(cid:258)lenia, czym s(cid:200) mikrous(cid:239)ugi, u(cid:285)ywane jest poj(cid:218)cie architektury SOA (ang. Service-Oriented Architecture, architektura zorientowana na us(cid:239)ugi). SOA — koncepcja tworzenia systemów informatycznych, w której g(cid:239)ówny nacisk stawia si(cid:218) na definiowanie us(cid:239)ug, spe(cid:239)niaj(cid:200)cych wymagania u(cid:285)ytkownika. (…) Mianem us(cid:239)ugi okre(cid:258)la si(cid:218) tu ka(cid:285)dy element oprogramowania, mog(cid:200)cy dzia(cid:239)a(cid:202) niezale(cid:285)nie od innych. — Wikipedia Element w powy(cid:285)szej definicji oznacza samodzieln(cid:200) us(cid:239)ug(cid:218), która implementuje pewn(cid:200) funk- cjonalno(cid:258)(cid:202) biznesow(cid:200) i udost(cid:218)pnia j(cid:200) poprzez okre(cid:258)lony interfejs. Cho(cid:202) architektura SOA okre(cid:258)la, (cid:285)e ka(cid:285)da us(cid:239)uga musi by(cid:202) niezale(cid:285)nym procesem, nie narzuca jednak rodzaju protoko(cid:239)ów wykorzystywanych przez procesy do komunikacji mi(cid:218)dzy sob(cid:200). Ogólnie definiuje te(cid:285) budow(cid:218) i sposób wdra(cid:285)ania aplikacji. W manife(cid:258)cie SOA (http://www.soa-manifesto.org), opublikowanym ok. 2009 r. przez grup(cid:218) ekspertów, nie ma te(cid:285) ani s(cid:239)owa o tym, jak us(cid:239)ugi powinny komunikowa(cid:202) si(cid:218) mi(cid:218)dzy sob(cid:200) za po(cid:258)rednictwem sieci. Us(cid:239)ugi SOA mog(cid:200) komunikowa(cid:202) si(cid:218) za pomoc(cid:200) protoko(cid:239)u IPC (ang. Inter-Process Communication, komunikacja mi(cid:218)dzyprocesowa), gniazd, wspó(cid:239)dzielonej pami(cid:218)ci, po(cid:258)rednich kolejek komunikatów, a nawet protoko(cid:239)u RPC (ang. Remote Procedure Calls, zdalne wywo(cid:239)ywanie procedur). Liczba dost(cid:218)pnych opcji jest bardzo du(cid:285)a. Krótko mówi(cid:200)c, archi- tektura SOA pasuje do ka(cid:285)dej aplikacji, która nie jest pojedynczym procesem. 18 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Czym s(cid:261) mikrous(cid:225)ugi? Cz(cid:218)sto s(cid:239)yszy si(cid:218), (cid:285)e mikrous(cid:239)uga jest wyspecjalizowan(cid:200) odmian(cid:200) architektury SOA. Jest tak dlatego, poniewa(cid:285) mikrous(cid:239)ugi realizuj(cid:200) kilka za(cid:239)o(cid:285)e(cid:241) tej architektury, m.in. umo(cid:285)liwiaj(cid:200) two- rzenie aplikacji z(cid:239)o(cid:285)onych z niezale(cid:285)nych komponentów komunikuj(cid:200)cych si(cid:218) ze sob(cid:200). Aby sformu(cid:239)owa(cid:202) pe(cid:239)n(cid:200) definicj(cid:218) mikrous(cid:239)ugi, nale(cid:285)y wcze(cid:258)niej przyjrze(cid:202) si(cid:218), jak zbudowana jest wi(cid:218)kszo(cid:258)(cid:202) aplikacji. Podej(cid:258)cie monolityczne Rozwa(cid:285)my bardzo prosty przyk(cid:239)ad tradycyjnej monolitycznej aplikacji: serwisu WWW do re- zerwowania miejsc w hotelach. Taka strona, oprócz statycznej tre(cid:258)ci HTML, zawiera funkcjo- nalno(cid:258)(cid:202) umo(cid:285)liwiaj(cid:200)c(cid:200) u(cid:285)ytkownikom rezerwowanie miejsc w hotelu w dowolnym mie(cid:258)cie na ca(cid:239)ym (cid:258)wiecie. U(cid:285)ytkownik wyszukuje odpowiedni hotel, a nast(cid:218)pnie rezerwuje w nim pokój i p(cid:239)aci kart(cid:200) kredytow(cid:200). Gdy u(cid:285)ytkownik szuka hotelu na stronie WWW, aplikacja wykonuje nast(cid:218)puj(cid:200)ce operacje: 1. Wysy(cid:239)a do bazy danych kilka zapyta(cid:241) SQL. 2. Wysy(cid:239)a zapytanie HTTP do s(cid:200)siedniej us(cid:239)ugi dodaj(cid:200)cej hotel do listy. 3. Generuje na podstawie szablonu wynikow(cid:200) stron(cid:218) HTML. Gdy u(cid:285)ytkownik wybierze odpowiedni hotel i kliknie go w celu zarezerwowania miejsca, aplikacja wykonuje nast(cid:218)puj(cid:200)ce operacje: 1. Tworzy konto u(cid:285)ytkownika, je(cid:285)eli jest to konieczne, a nast(cid:218)pnie uwierzytelnia go. 2. Komunikuje si(cid:218) z us(cid:239)ug(cid:200) bankowo(cid:258)ci internetowej w celu dokonania p(cid:239)atno(cid:258)ci. 3. W procesie p(cid:239)atno(cid:258)ci wykorzystuje dane u(cid:285)ytkownika zapisane w bazie. 4. Przygotowuje potwierdzenie za pomoc(cid:200) generatora plików PDF. 5. Za pomoc(cid:200) us(cid:239)ugi e-mail wysy(cid:239)a potwierdzenie do u(cid:285)ytkownika. 6. Do hotelu wysy(cid:239)a wiadomo(cid:258)(cid:202) e-mail z potwierdzeniem. 7. W bazie danych tworzy rekord rezerwacji. Jest to oczywi(cid:258)cie model uproszczony, ale oddaj(cid:200)cy rzeczywisto(cid:258)(cid:202). Aplikacja komunikuje si(cid:218) z baz(cid:200) danych zawieraj(cid:200)c(cid:200) informacje o hotelu, szczegó(cid:239)y rezerwacji, p(cid:239)atno(cid:258)ci, dane u(cid:285)ytkownika itp. Komunikuje si(cid:218) równie(cid:285) z zewn(cid:218)trznymi us(cid:239)ugami wysy(cid:239)aj(cid:200)cymi wiadomo(cid:258)ci e-mail, realizuj(cid:200)cymi p(cid:239)atno(cid:258)ci i dostarczaj(cid:200)cymi informacji o innych hotelach. Zgodnie ze star(cid:200), dobr(cid:200) architektur(cid:200) LAMP (ang. Linux-Apache-MySQL-Perl/PHP/Python) ka(cid:285)de odebrane zapytanie HTTP generuje lawin(cid:218) zapyta(cid:241) SQL do bazy danych, przez sie(cid:202) przesy(cid:239)anych jest wiele zapyta(cid:241) do zewn(cid:218)trznych us(cid:239)ug, po czym serwer, wykorzystuj(cid:200)c sza- blon, tworzy kod HTML strony wynikowej. 19 Poleć książkęKup książkę Rozwijanie mikrous(cid:225)ug w Pythonie Poni(cid:285)szy diagram ilustruje scentralizowan(cid:200) architektur(cid:218) aplikacji: Jest to typowa, monolityczna aplikacja, maj(cid:200)ca wiele niew(cid:200)tpliwych zalet. Podstawow(cid:200) zalet(cid:200) jest jeden kod. Dzi(cid:218)ki temu rozpocz(cid:218)cie projektu tworzenia aplikacji jest (cid:239)atwiejsze. Zakodowanie testów jest (cid:239)atwe, a samemu kodowi mo(cid:285)na nada(cid:202) przejrzyst(cid:200) struk- tur(cid:218). Umieszczenie wszystkich danych w jednej bazie równie(cid:285) upraszcza kodowanie aplikacji. Mo(cid:285)na modyfikowa(cid:202) model danych i sposób pobierania ich za pomoc(cid:200) kodu. Wdro(cid:285)enie takiej aplikacji to te(cid:285) (cid:285)aden problem: kod trzeba skompilowa(cid:202) do pakietu i uru- chomi(cid:202) go na jakim(cid:258) serwerze. Aby wyskalowa(cid:202) aplikacj(cid:218), wystarczy uruchomi(cid:202) jej kolejne instancje i kilka baz danych razem z jakim(cid:258) mechanizmem replikacyjnym. Dopóki aplikacja jest ma(cid:239)a, ten model si(cid:218) sprawdza. Poza tym aplikacj(cid:218) mo(cid:285)e z (cid:239)atwo(cid:258)ci(cid:200) utrzymywa(cid:202) jeden zespó(cid:239) administratorów. Projekty jednak maj(cid:200) to do siebie, (cid:285)e rozrastaj(cid:200) si(cid:218) do rozmiarów wi(cid:218)kszych ni(cid:285) zak(cid:239)adane na pocz(cid:200)tku. Je(cid:285)eli jest jeden kod aplikacji, wtedy zaczynaj(cid:200) si(cid:218) pojawia(cid:202) powa(cid:285)ne problemy. Gdy trzeba wprowadzi(cid:202) du(cid:285)(cid:200) zmian(cid:218), na przyk(cid:239)ad zmieni(cid:202) us(cid:239)ug(cid:218) bankow(cid:200) lub baz(cid:218) danych, wtedy aplikacja wchodzi w bardzo niestabilny stan. Taka zmiana jest powa(cid:285)nym problemem w cyklu (cid:285)ycia projektu, a wdro(cid:285)enie nowej wersji aplikacji wymaga jej dodatkowego przete- stowania. A takie zmiany zdarzaj(cid:200) si(cid:218) cz(cid:218)sto. Ma(cid:239)e zmiany te(cid:285) mog(cid:200) by(cid:202) przyczyn(cid:200) k(cid:239)opotów, poniewa(cid:285) ka(cid:285)da cz(cid:218)(cid:258)(cid:202) systemu ma inne wy- magania dotycz(cid:200)ce niezawodno(cid:258)ci i stabilno(cid:258)ci. Nara(cid:285)enie procesów rezerwacji i p(cid:239)atno(cid:258)ci na ryzyko z powodu wadliwej funkcji generuj(cid:200)cej pliki PDF to jeden z tego rodzaju problemów. Kolejn(cid:200) kwesti(cid:200) jest niekontrolowany rozrost aplikacji. Wci(cid:200)(cid:285) rozszerza si(cid:218) j(cid:200) o nowe funkcjo- nalno(cid:258)ci, a gdy z projektu odchodz(cid:200) jacy(cid:258) programi(cid:258)ci i do(cid:239)(cid:200)czaj(cid:200) nowi, wtedy kod robi si(cid:218) coraz bardziej zagmatwany, co spowalnia jego testowanie. W efekcie powstaje kod popl(cid:200)tany jak spaghetti, trudny w utrzymaniu, korzystaj(cid:200)cy ze skomplikowanej bazy danych wymagaj(cid:200)- cej stosowania z(cid:239)o(cid:285)onych procedur migracyjnych za ka(cid:285)dym razem gdy programista zmieni model danych. 20 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Czym s(cid:261) mikrous(cid:225)ugi? Du(cid:285)e projekty informatyczne dojrzewaj(cid:200) kilka lat i powoli pojawia si(cid:218) w nich niesamowity ba(cid:239)agan, z którym trudno jest sobie poradzi(cid:202). I to nie z powodu niekompetencji programi- stów, tylko dlatego, (cid:285)e kod jest coraz bardziej z(cid:239)o(cid:285)ony, a osób, które w pe(cid:239)ni rozumiej(cid:200) skutki wprowadzanych niewielkich zmian, jest coraz mniej. Ka(cid:285)dy cz(cid:239)onek zespo(cid:239)u pracuje osobno na niewielkim fragmencie kodu, a gdy spojrzy si(cid:218) na niego z szerszej perspektywy, wida(cid:202) jeden wielki ba(cid:239)agan. Wszyscy to przerabiali(cid:258)my. Programi(cid:258)ci pracuj(cid:200)cy nad takimi projektami marz(cid:200) o tym, aby napisa(cid:202) kod aplikacji od pod- staw, wykorzystuj(cid:200)c przy tym najnowsze platformy. W ten sposób jednak wpadaj(cid:200) w t(cid:218) sam(cid:200) pu(cid:239)apk(cid:218) i historia si(cid:218) powtarza. Poni(cid:285)sza lista podsumowuje zalety i wady monolitycznego podej(cid:258)cia podczas tworzenia aplikacji: (cid:81) Rozpocz(cid:218)cie projektu jest proste. (cid:81) Scentralizowana baza u(cid:239)atwia projektowanie i porz(cid:200)dkowanie danych. (cid:81) Wdro(cid:285)enie aplikacji jest proste. (cid:81) Wszelkie zmiany w kodzie mog(cid:200) mie(cid:202) wp(cid:239)yw na pozornie niezwi(cid:200)zane z nimi funkcjonalno(cid:258)ci. Je(cid:285)eli która(cid:258) z nich przestanie dzia(cid:239)a(cid:202), awarii mo(cid:285)e ulec ca(cid:239)a aplikacja. (cid:81) Mo(cid:285)liwo(cid:258)ci skalowania aplikacji s(cid:200) ograniczone: mo(cid:285)na uruchamia(cid:202) kilka instancji, ale je(cid:285)eli jedna z funkcjonalno(cid:258)ci zajmie wszystkie dost(cid:218)pne zasoby, wtedy problem obejmuje ca(cid:239)y system. (cid:81) W miar(cid:218) powi(cid:218)kszania si(cid:218) kodu coraz trudniej jest utrzymywa(cid:202) w nim porz(cid:200)dek. S(cid:200) oczywi(cid:258)cie sposoby unikni(cid:218)cia niektórych opisanych powy(cid:285)ej problemów. Oczywistym rozwi(cid:200)zaniem jest podzielenie aplikacji na osobne cz(cid:218)(cid:258)ci, nawet je(cid:285)eli kod wyni- kowy b(cid:218)dzie uruchamiany w ramach jednego procesu. Do tego celu programi(cid:258)ci wykorzy- stuj(cid:200) zewn(cid:218)trzne biblioteki i platformy, rozwijane wewn(cid:218)trznie lub przez spo(cid:239)eczno(cid:258)(cid:202) OSS (ang. Open Source Software, otwarte oprogramowanie). Je(cid:285)eli do tworzenia aplikacji w j(cid:218)zyku Python u(cid:285)yje si(cid:218) platformy takiej jak Flask, wtedy mo(cid:285)na skupi(cid:202) si(cid:218) na algorytmie. Ponadto bardzo atrakcyjna jest mo(cid:285)liwo(cid:258)(cid:202) wydzielenia frag- mentów kodu w postaci rozszerze(cid:241) Flask lub pakietów Python. Dodatkowo, podzielenie kodu na ma(cid:239)e pakiety jest cz(cid:218)sto dobrym sposobem kontrolowania rozrostu aplikacji. Ma(cid:239)e jest pi(cid:218)kne. — Filozofia systemu UNIX 21 Poleć książkęKup książkę Rozwijanie mikrous(cid:225)ug w Pythonie Na przyk(cid:239)ad generator plików PDF w opisanej wcze(cid:258)niej aplikacji rezerwacyjnej mo(cid:285)e by(cid:202) osobnym pakietem wykorzystuj(cid:200)cym bibliotek(cid:218) Reportlab i kilka szablonów. Taki pakiet móg(cid:239)by by(cid:202) wykorzystywany równie(cid:285) w innych aplikacjach, a nawet udost(cid:218)pniony spo(cid:239)eczno(cid:258)ci programistów w serwisie PyPI (Python Package Index). Jednak w przypadku tworzenia jednocz(cid:218)(cid:258)ciowej aplikacji wci(cid:200)(cid:285) wyst(cid:218)puje kilka problemów, na przyk(cid:239)ad brak mo(cid:285)liwo(cid:258)ci ró(cid:285)nego skalowania jej poszczególnych fragmentów lub b(cid:239)(cid:218)dy w wykorzystywanych zale(cid:285)no(cid:258)ciach. Korzystanie z zale(cid:285)no(cid:258)ci wi(cid:200)(cid:285)e si(cid:218) z kolejnymi wyzwaniami, które okre(cid:258)la si(cid:218) mianem piek(cid:239)a zale(cid:285)no(cid:258)ci. Je(cid:285)eli jaki(cid:258) fragment aplikacji korzysta z biblioteki, ale na przyk(cid:239)ad generator plików PDF wymaga stosowania tylko jej okre(cid:258)lonej wersji, wtedy zazwyczaj trzeba szuka(cid:202) jakiego(cid:258) prowizorycznego rozwi(cid:200)zania zast(cid:218)pczego albo tworzy(cid:202) w(cid:239)asn(cid:200) wersj(cid:218) zale(cid:285)no(cid:258)ci. Oczywi(cid:258)cie opisane tu problemy nie ujawniaj(cid:200) si(cid:218) dopiero w godzinie zero, gdy projekt ju(cid:285) startuje, ale narastaj(cid:200) stopniowo w miar(cid:218) up(cid:239)ywu czasu. Przyjrzyjmy si(cid:218) teraz, jak wygl(cid:200)da(cid:239)aby aplikacja zbudowana z mikrous(cid:239)ug. Podej(cid:258)cie mikrous(cid:239)ugowe Gdyby(cid:258)my chcieli zbudowa(cid:202) t(cid:218) sam(cid:200) aplikacj(cid:218) z mikrous(cid:239)ug, mo(cid:285)na by by(cid:239)o podzieli(cid:202) jej kod na kilka osobnych komponentów uruchamianych w oddzielnych procesach. Zamiast jednej aplikacji realizuj(cid:200)cej wszystkie funkcjonalno(cid:258)ci by(cid:239)oby wiele ró(cid:285)nych mikrous(cid:239)ug, jak na po- ni(cid:285)szym rysunku. 22 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Czym s(cid:261) mikrous(cid:225)ugi? Niech Ci(cid:218) nie przera(cid:285)a liczba komponentów na tym diagramie. Po prostu po podzieleniu mo- nolitycznej aplikacji na cz(cid:218)(cid:258)ci zosta(cid:239)a ujawniona jej wewn(cid:218)trzna komunikacja. Po nieznacznym uproszczeniu schematu mo(cid:285)na w nim wyró(cid:285)ni(cid:202) siedem niezale(cid:285)nych komponentów: 1. Interfejs u(cid:285)ytkownika: frontalna us(cid:239)uga generuj(cid:200)ca stron(cid:218) WWW i komunikuj(cid:200)ca si(cid:218) z innymi mikrous(cid:239)ugami. 2. Generowanie PDF: bardzo prosta us(cid:239)uga tworz(cid:200)ca potwierdzenia i inne dokumenty w formacie PDF na podstawie szablonów i danych. 3. Wyszukiwanie: us(cid:239)uga tworz(cid:200)ca list(cid:218) hoteli w danym mie(cid:258)cie. Us(cid:239)uga ta korzysta z w(cid:239)asnej bazy danych. 4. P(cid:239)atno(cid:258)ci: us(cid:239)uga komunikuj(cid:200)ca si(cid:218) z us(cid:239)ug(cid:200) bankow(cid:200), korzystaj(cid:200)ca z bazy danych o p(cid:239)atno(cid:258)ciach i wysy(cid:239)aj(cid:200)ca wiadomo(cid:258)ci e-mail potwierdzaj(cid:200)ce dokonanie p(cid:239)atno(cid:258)ci. 5. Rezerwacje: us(cid:239)uga przechowuj(cid:200)ca informacje o rezerwacjach i tworz(cid:200)ca pliki PDF. 6. U(cid:285)ytkownicy: us(cid:239)uga przechowuj(cid:200)ca informacje o u(cid:285)ytkownikach i wysy(cid:239)aj(cid:200)ca do nich wiadomo(cid:258)ci e-mail. 7. Uwierzytelnienie: us(cid:239)uga stosuj(cid:200)ca standard OAuth 2.0, generuj(cid:200)ca tokeny wykorzystywane przez inne us(cid:239)ugi do uwierzytelniania u(cid:285)ytkowników. Powy(cid:285)sze mikrous(cid:239)ugi wraz z dodatkowymi us(cid:239)ugami, na przyk(cid:239)ad poczt(cid:200) e-mail, oferuj(cid:200) funkcjonalno(cid:258)ci podobne jak monolityczna aplikacja. Jednak w tym przypadku poszczególne komponenty komunikuj(cid:200) si(cid:218) ze sob(cid:200) za pomoc(cid:200) protoko(cid:239)u HTTP, a funkcjonalno(cid:258)ci s(cid:200) udo- st(cid:218)pniane za pomoc(cid:200) protoko(cid:239)u REST. Nie ma tu jednej centralnej bazy danych. Ka(cid:285)da mikrous(cid:239)uga korzysta z w(cid:239)asnej wewn(cid:218)trznej bazy, a dane odbiera i wysy(cid:239)a za pomoc(cid:200) zapyta(cid:241) HTTP i niezale(cid:285)nych od j(cid:218)zyków progra- mowania formatów JSON, XML lub YAML. Us(cid:239)uga interfejsu u(cid:285)ytkownika ró(cid:285)ni si(cid:218) nieco od pozosta(cid:239)ych, poniewa(cid:285) generuje stron(cid:218) WWW. W zale(cid:285)no(cid:258)ci od wykorzystywanej przez ni(cid:200) platformy wynikiem dzia(cid:239)ania us(cid:239)ugi mo(cid:285)e by(cid:202) zestaw plików HTML i JSON albo wr(cid:218)cz tylko plik JSON, je(cid:285)eli po stronie klienta urucha- miany jest statyczny skrypt JavaScript tworz(cid:200)cy stron(cid:218) w przegl(cid:200)darce. Poza wyj(cid:200)tkow(cid:200) us(cid:239)ug(cid:200) interfejsu u(cid:285)ytkownika wszystkie pozosta(cid:239)e mikrous(cid:239)ugi komunikuj(cid:200) si(cid:218) ze sob(cid:200) za pomoc(cid:200) protoko(cid:239)u HTTP, tworz(cid:200)c w ten sposób kompletn(cid:200) aplikacj(cid:218). W tym kontek(cid:258)cie mikrous(cid:239)ugi stanowi(cid:200) logiczne jednostki, z których ka(cid:285)da wykonuje wy(cid:239)(cid:200)cz- nie jedno (cid:258)ci(cid:258)le okre(cid:258)lone zadanie. Nasza propozycja definicji mikrous(cid:239)ugi brzmi nast(cid:218)puj(cid:200)co: Mikrous(cid:239)uga jest to bardzo prosta aplikacja oferuj(cid:200)ca w(cid:200)ski zakres funkcjonalno(cid:258)ci w (cid:258)ci(cid:258)le okre(cid:258)lonym kontek(cid:258)cie. Jest to komponent odpowiedzialny za jedn(cid:200) funkcj(cid:218), który mo(cid:285)na rozwija(cid:202) i wdra(cid:285)a(cid:202) nieza- le(cid:285)nie od innych komponentów. 23 Poleć książkęKup książkę Rozwijanie mikrous(cid:225)ug w Pythonie Powy(cid:285)sza definicja nie wspomina o protokole HTTP ani o formacie JSON, poniewa(cid:285) obejmuje równie(cid:285) na przyk(cid:239)ad ma(cid:239)(cid:200) us(cid:239)ug(cid:218) wykorzystuj(cid:200)c(cid:200) protokó(cid:239) UDP do przesy(cid:239)ania danych binarnych. Jednak w przypadku opisanej aplikacji oraz w przyk(cid:239)adowych kodach opisanych w tej ksi(cid:200)(cid:285)ce wszystkie mikrous(cid:239)ugi, z wyj(cid:200)tkiem interfejsu u(cid:285)ytkownika, s(cid:200) prostymi aplikacjami WWW wykorzystuj(cid:200)cymi protokó(cid:239) HTTP, wysy(cid:239)aj(cid:200)cymi i odbieraj(cid:200)cymi dane w formacie JSON. Zalety mikrous(cid:239)ug Cho(cid:202) architektura mikrous(cid:239)ugowa wydaje si(cid:218) bardziej skomplikowana od monolitycznej, ma w porównaniu z ni(cid:200) wi(cid:218)cej zalet, mi(cid:218)dzy innymi: (cid:81) pozwala rozdziela(cid:202) zakresy odpowiedzialno(cid:258)ci, (cid:81) mo(cid:285)na j(cid:200) dzieli(cid:202) na mniejsze projekty, (cid:81) oferuje wi(cid:218)cej opcji skalowania i wdra(cid:285)ania. W kolejnych cz(cid:218)(cid:258)ciach powy(cid:285)sze zalety opisane s(cid:200) dok(cid:239)adniej. Rozdzielenie zakresów odpowiedzialno(cid:258)ci Przede wszystkim ka(cid:285)d(cid:200) mikrous(cid:239)ug(cid:218) mo(cid:285)e rozwija(cid:202) osobny, niezale(cid:285)ny zespó(cid:239). Na przyk(cid:239)ad tworzenie us(cid:239)ugi rezerwacji mo(cid:285)e by(cid:202) osobnym projektem. Odpowiedzialny za ni(cid:200) zespó(cid:239) mo(cid:285)e u(cid:285)ywa(cid:202) dowolnego j(cid:218)zyka programowania i bazy danych, o ile tylko dobrze udokumentuje interfejs HTTP API. Rozdzielenie zakresów odpowiedzialno(cid:258)ci oznacza równie(cid:285), (cid:285)e rozwój aplikacji mo(cid:285)na (cid:258)ci(cid:258)lej kontrolowa(cid:202) ni(cid:285) w podej(cid:258)ciu monolitycznym. Na przyk(cid:239)ad zmiana komunikacji systemu ob- s(cid:239)ugi p(cid:239)atno(cid:258)ci z bankiem b(cid:218)dzie dotyczy(cid:239)a tylko danej us(cid:239)ugi, a pozosta(cid:239)a cz(cid:218)(cid:258)(cid:202) aplikacji po- zostanie nienaruszona i b(cid:218)dzie dalej dzia(cid:239)a(cid:202) stabilnie. Lu(cid:283)ne sprz(cid:218)ganie us(cid:239)ug znakomicie przyspiesza rozwój projektu. Filozofia takiego podej(cid:258)cia jest podobna do zasady pojedynczej odpowiedzialno(cid:258)ci zdefiniowanej przez Roberta Martina. Zgodnie z t(cid:200) zasad(cid:200) powód zmiany dowolnej klasy mo(cid:285)e by(cid:202) tylko jeden. Innymi s(cid:239)owy, ka(cid:285)da klasa powinna oferowa(cid:202) jedn(cid:200), (cid:258)ci(cid:258)le okre(cid:258)lon(cid:200) funkcjonalno(cid:258)(cid:202). W odniesieniu do mikrous(cid:239)ug zasada ta oznacza, (cid:285)e ka(cid:285)da mikrous(cid:239)uga odgrywa w aplikacji tylko jedn(cid:200) rol(cid:218). Mniejsze projekty Drug(cid:200) zalet(cid:200) podej(cid:258)cia mikrous(cid:239)ugowego jest rozdzielenie z(cid:239)o(cid:285)ono(cid:258)ci projektu. Gdy aplikacja jest rozbudowywana o kolejn(cid:200) funkcjonalno(cid:258)(cid:202), na przyk(cid:239)ad generowanie plików PDF, jej kod si(cid:218) powi(cid:218)ksza, nawet je(cid:285)eli robi si(cid:218) to w uporz(cid:200)dkowany sposób. Kod staje si(cid:218) bardziej skompliko- wany i czasami dzia(cid:239)a wolniej. Problem rozwi(cid:200)zuje implementowanie nowej funkcjonalno(cid:258)ci 24 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Czym s(cid:261) mikrous(cid:225)ugi? w postaci osobnej aplikacji. W ten sposób (cid:239)atwiej jest tworzy(cid:202) potrzebne funkcjonalno(cid:258)ci. Ponadto mo(cid:285)na je cz(cid:218)sto zmienia(cid:202), a poniewa(cid:285) cykle udost(cid:218)pniania nowych wersji s(cid:200) krótsze, aplikacja spe(cid:239)nia bie(cid:285)(cid:200)ce potrzeby u(cid:285)ytkowników. Rozwój aplikacji znajduje si(cid:218) pod pe(cid:239)n(cid:200) kontrol(cid:200). Mniejsze projekty redukuj(cid:200) równie(cid:285) ryzyko wyst(cid:200)pienia problemów podczas usprawniania aplikacji. Je(cid:285)eli programi(cid:258)ci zechc(cid:200) wypróbowa(cid:202) najnowsz(cid:200) wersj(cid:218) j(cid:218)zyka programowania lub platformy, mog(cid:200) szybko przygotowa(cid:202) prototyp oferuj(cid:200)cy ten sam interfejs API, przetestowa(cid:202) go i zadecydowa(cid:202) o kontynuowaniu prac w tym kierunku. Praktycznym przyk(cid:239)adem takiego podej(cid:258)cia jest mikrous(cid:239)uga Firefox Sync. Obecnie prowa- dzone s(cid:200) pewne eksperymenty nad przej(cid:258)ciem z aktualnie wykorzystywanego j(cid:218)zyka Python i bazy MySQL na j(cid:218)zyk Go i baz(cid:218) SQLite. Prototyp jest w fazie bardzo eksperymentalnej, ale dzi(cid:218)ki temu, (cid:285)e wydzielili(cid:258)my osobn(cid:200) mikrous(cid:239)ug(cid:218) przechowuj(cid:200)c(cid:200) dane i zdefiniowali(cid:258)my in- terfejs HTTP API, (cid:239)atwo b(cid:218)dzie przetestowa(cid:202) j(cid:200) na wybranej ma(cid:239)ej grupie u(cid:285)ytkowników. Skalowanie i wdra(cid:285)anie Wreszcie dzi(cid:218)ki podzieleniu aplikacji na mniejsze komponenty (cid:239)atwiej jest j(cid:200) skalowa(cid:202) w za- le(cid:285)no(cid:258)ci od warunków. Za(cid:239)ó(cid:285)my, (cid:285)e z aplikacji korzysta ka(cid:285)dego dnia bardzo wielu u(cid:285)ytkow- ników, a mikrous(cid:239)uga generuj(cid:200)ca pliki PDF znacznie obci(cid:200)(cid:285)a procesor. W takim przypadku wystarczy uruchomi(cid:202) t(cid:218) jedn(cid:200) mikrous(cid:239)ug(cid:218) na kilku serwerach wyposa(cid:285)onych w bardziej wy- dajne procesory. Innym przyk(cid:239)adem s(cid:200) mikrous(cid:239)ugi wykorzystuj(cid:200)ce pami(cid:218)(cid:202) RAM, na przyk(cid:239)ad komunikuj(cid:200)ce si(cid:218) z baz(cid:200) Redis lub Memcache. Tego rodzaju us(cid:239)ugi mo(cid:285)na uruchamia(cid:202) na serwerach wypo- sa(cid:285)onych w s(cid:239)absze procesory, ale maj(cid:200)cych znacznie wi(cid:218)ksz(cid:200) pami(cid:218)(cid:202). Zalety mikrous(cid:239)ug mo(cid:285)na podsumowa(cid:202) nast(cid:218)puj(cid:200)co: (cid:81) Zespo(cid:239)y programistów mog(cid:200) rozwija(cid:202) us(cid:239)ugi niezale(cid:285)nie od siebie i u(cid:285)ywa(cid:202) dowolnych technologii. Mog(cid:200) definiowa(cid:202) w(cid:239)asne cykle udost(cid:218)pniania nowych wersji us(cid:239)ug. Wymagane jest tylko udost(cid:218)pnienie niezale(cid:285)nego od j(cid:218)zyka programowania interfejsu HTTP API. (cid:81) Programi(cid:258)ci mog(cid:200) dzieli(cid:202) skomplikowan(cid:200) aplikacj(cid:218) na logiczne komponenty. Ka(cid:285)da mikrous(cid:239)uga wykonuje tylko jedno zadanie, ale za to wykonuje je dobrze. (cid:81) Niektóre us(cid:239)ugi mog(cid:200) by(cid:202) niezale(cid:285)nymi aplikacjami. Dzi(cid:218)ki temu mo(cid:285)na lepiej kontrolowa(cid:202) wdra(cid:285)anie aplikacji i (cid:239)atwiej j(cid:200) skalowa(cid:202). Architektura mikrous(cid:239)ugowa pozwala rozwi(cid:200)za(cid:202) mnóstwo problemów pojawiaj(cid:200)cych si(cid:218) w miar(cid:218) rozbudowy aplikacji. Nale(cid:285)y jednak mie(cid:202) (cid:258)wiadomo(cid:258)(cid:202) zwi(cid:200)zanych z nimi innych praktycznych kwestii. 25 Poleć książkęKup książkę Rozwijanie mikrous(cid:225)ug w Pythonie Wady mikrous(cid:239)ug Jak wcze(cid:258)niej wspomnia(cid:239)em, budowanie aplikacji z mikrous(cid:239)ug ma wiele zalet, ale nie jest z(cid:239)otym (cid:258)rodkiem na wszystkie problemy. Nale(cid:285)y pami(cid:218)ta(cid:202) o nast(cid:218)puj(cid:200)cych najwa(cid:285)niejszych problemach, jakie mog(cid:200) pojawi(cid:202) si(cid:218) pod- czas kodowania mikrous(cid:239)ug: (cid:81) nielogiczny podzia(cid:239) aplikacji, (cid:81) wi(cid:218)cej interakcji sieciowych, (cid:81) powielanie danych, (cid:81) problemy z kompatybilno(cid:258)ci(cid:200), (cid:81) skomplikowane testy. W kolejnych cz(cid:218)(cid:258)ciach powy(cid:285)sze problemy opisane s(cid:200) dok(cid:239)adniej. Nielogiczny podzia(cid:239) aplikacji Podstawow(cid:200) kwesti(cid:200) w podej(cid:258)ciu mikrous(cid:239)ugowym jest zaprojektowanie architektury aplika- cji. Jest rzecz(cid:200) niemo(cid:285)liw(cid:200), aby zespó(cid:239) programistów za pierwszym razem zdefiniowa(cid:239) idealn(cid:200) architektur(cid:218). Niektóre mikrous(cid:239)ugi, na przyk(cid:239)ad generator plików PDF, s(cid:200) oczywiste, ale w zale(cid:285)no(cid:258)ci od algorytmu istnieje du(cid:285)e prawdopodobie(cid:241)stwo, (cid:285)e zanim podzieli si(cid:218) go na odpowiednie mikrous(cid:239)ugi, kod ju(cid:285) b(cid:218)dzie na tyle rozwini(cid:218)ty, (cid:285)e w(cid:239)a(cid:258)ciwy podzia(cid:239) oka(cid:285)e si(cid:218) niemo(cid:285)liwy do przeprowadzenia. Architektura musi dojrzewa(cid:202) w cyklach prób i b(cid:239)(cid:218)dów. Dodawanie i usuwanie mikrous(cid:239)ug mo(cid:285)e by(cid:202) bardziej uci(cid:200)(cid:285)liwe ni(cid:285) tworzenie monolitycznej aplikacji. Ten problem mo(cid:285)na roz- wi(cid:200)za(cid:202), unikaj(cid:200)c dzielenia aplikacji na mikrous(cid:239)ugi, je(cid:285)eli powody nie s(cid:200) oczywiste. Pochopne dzielenie aplikacji jest (cid:283)ród(cid:239)em wszelkiego z(cid:239)a. Je(cid:285)eli masz jakiekolwiek w(cid:200)tpliwo(cid:258)ci, czy dany podzia(cid:239) jest w(cid:239)a(cid:258)ciwy, bezpieczniej b(cid:218)dzie po- zostawi(cid:202) kod w jednej cz(cid:218)(cid:258)ci. Zawsze (cid:239)atwiej jest pó(cid:283)niej podzieli(cid:202) go na nowe mikrous(cid:239)ugi, ni(cid:285) (cid:239)(cid:200)czy(cid:202) kod dwóch mikrous(cid:239)ug w jedn(cid:200) ca(cid:239)o(cid:258)(cid:202), gdy decyzja o podziale oka(cid:285)e si(cid:218) b(cid:239)(cid:218)dna. Je(cid:285)eli na przyk(cid:239)ad zawsze trzeba instalowa(cid:202) dwie okre(cid:258)lone us(cid:239)ugi razem lub je(cid:285)eli zmia- na wprowadzona w jednej z nich wp(cid:239)ywa na model danych w innej, oznacza to, (cid:285)e praw- dopodobnie mikrous(cid:239)ugi nie zosta(cid:239)y wyodr(cid:218)bnione poprawnie i nale(cid:285)y je z powrotem ze sob(cid:200) po(cid:239)(cid:200)czy(cid:202). 26 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Czym s(cid:261) mikrous(cid:225)ugi? Wi(cid:218)cej interakcji sieciowych Innym problemem jest zwi(cid:218)kszona ilo(cid:258)(cid:202) interakcji sieciowych wewn(cid:200)trz aplikacji. W wersji monolitycznej, nawet je(cid:285)eli kod jest zagmatwany, wszystkie operacje wykonywane s(cid:200) przez jeden proces, a wyniki s(cid:200) wysy(cid:239)ane do u(cid:285)ytkownika bez konieczno(cid:258)ci wcze(cid:258)niejszego odwo- (cid:239)ywania si(cid:218) do licznych us(cid:239)ug w tle. Trzeba zwróci(cid:202) szczególn(cid:200) uwag(cid:218) na sposób odwo(cid:239)ywania si(cid:218) do us(cid:239)ug w tle i odpowiedzie(cid:202) sobie na nast(cid:218)puj(cid:200)ce pytania: (cid:81) Co si(cid:218) stanie, gdy interfejs u(cid:285)ytkownika nie b(cid:218)dzie móg(cid:239) korzysta(cid:202) z us(cid:239)ugi generuj(cid:200)cej pliki PDF z powodu jej przeci(cid:200)(cid:285)enia lub z powodu przerwy w komunikacji sieciowej? (cid:81) Czy interfejs u(cid:285)ytkownika odwo(cid:239)uje si(cid:218) do innych us(cid:239)ug w sposób synchroniczny, czy te(cid:285) asynchroniczny? (cid:81) Jak sposób odwo(cid:239)ywania si(cid:218) od us(cid:239)ug wp(cid:239)ywa na czas odpowiedzi interfejsu u(cid:285)ytkownika? Aby odpowiedzie(cid:202) na powy(cid:285)sze pytania, potrzebna jest przemy(cid:258)lana strategia rozwoju aplikacji, o czym b(cid:218)dzie mowa w rozdziale 5, „Interakcje z innymi us(cid:239)ugami”. Powielanie danych Kolejnym problemem jest przechowywanie i wspó(cid:239)dzielenie danych. Skuteczna mikrous(cid:239)uga powinna by(cid:202) niezale(cid:285)na od innych mikrous(cid:239)ug i w idealnym przypadku nie powinna wspó(cid:239)- dzieli(cid:202) z nimi swojej bazy danych. Co to oznacza w przypadku aplikacji rezerwacyjnej? Tak jak poprzednio, pojawia si(cid:218) w tym momencie wiele pyta(cid:241), na przyk(cid:239)ad: (cid:81) Czy we wszystkich bazach danych identyfikator danego u(cid:285)ytkownika powinien by(cid:202) taki sam, czy te(cid:285) ka(cid:285)da us(cid:239)uga musi definiowa(cid:202) go niezale(cid:285)nie jako ukryty szczegó(cid:239) implementacyjny? (cid:81) Gdy do systemu zostanie dodany nowy u(cid:285)ytkownik, czy nale(cid:285)y replikowa(cid:202) jego dane w innych bazach, stosuj(cid:200)c odpowiedni(cid:200) strategi(cid:218), na przyk(cid:239)ad pompowanie danych, czy te(cid:285) jest to zb(cid:218)dna operacja? (cid:81) W jaki sposób dane maj(cid:200) by(cid:202) usuwane z bazy? Nie jest (cid:239)atwo znale(cid:283)(cid:202) odpowiedzi na powy(cid:285)sze pytania, a ponadto istnieje wiele sposobów rozwi(cid:200)zywania tego rodzaju problemów, o czym dowiesz si(cid:218) z tej ksi(cid:200)(cid:285)ki. Maksymalne redukowanie duplikacji danych przy jednoczesnym izolowaniu us(cid:239)ug jest jednym z najwi(cid:218)k- szych wyzwa(cid:241) towarzysz(cid:200)cych tworzeniu aplikacji opartych na mikrous(cid:239)ugach. 27 Poleć książkęKup książkę Rozwijanie mikrous(cid:225)ug w Pythonie Problemy z kompatybilno(cid:258)ci(cid:200) Inne problemy pojawiaj(cid:200) si(cid:218) w przypadku, gdy zmiana okre(cid:258)lonej funkcjonalno(cid:258)ci wp(cid:239)ywa na kilka mikrous(cid:239)ug. Je(cid:285)eli zmiana nie zapewnia wstecznej kompatybilno(cid:258)ci us(cid:239)ugi i zak(cid:239)óca przep(cid:239)yw danych mi(cid:218)dzy mikrous(cid:239)ugami, wtedy pojawiaj(cid:200) si(cid:218) k(cid:239)opoty. Czy nale(cid:285)y wdra(cid:285)a(cid:202) now(cid:200) us(cid:239)ug(cid:218) wspó(cid:239)pracuj(cid:200)c(cid:200) ze starszymi wersjami innych us(cid:239)ug? Czy te(cid:285) trzeba zmienia(cid:202) kilka us(cid:239)ug jednocze(cid:258)nie? Czy to oznacza, (cid:285)e takie us(cid:239)ugi powinny zosta(cid:202) z powrotem scalone? Dokumentowanie wersji kodu us(cid:239)ugi i utrzymywanie dyscypliny w jej interfejsie API pozwala unikn(cid:200)(cid:202) tego typu problemów, o czym przekonasz si(cid:218) w drugiej cz(cid:218)(cid:258)ci ksi(cid:200)(cid:285)ki po(cid:258)wi(cid:218)conej kodowaniu przyk(cid:239)adowej aplikacji. Skomplikowane testy Na koniec, gdy trzeba wykona(cid:202) ca(cid:239)o(cid:258)ciowe testy i wdro(cid:285)y(cid:202) gotow(cid:200) aplikacj(cid:218), nale(cid:285)y rozwa(cid:285)y(cid:202) kilka kwestii. Aby proces rozwoju aplikacji by(cid:239) sprawny, musi by(cid:202) spójny i elastyczny. Musi istnie(cid:202) mo(cid:285)liwo(cid:258)(cid:202) korzystania z ca(cid:239)ej aplikacji w trakcie jej rozwijania. Testuj(cid:200)c jeden jej fragment, nie mo(cid:285)na mie(cid:202) pewno(cid:258)ci, (cid:285)e ca(cid:239)o(cid:258)(cid:202) b(cid:218)dzie dzia(cid:239)a(cid:202) poprawnie. Na szcz(cid:218)(cid:258)cie istnieje wiele narz(cid:218)dzi u(cid:239)atwiaj(cid:200)cych wdra(cid:285)anie aplikacji z(cid:239)o(cid:285)onych z wielu komponentów, o czym dowiesz si(cid:218) w dalszej cz(cid:218)(cid:258)ci ksi(cid:200)(cid:285)ki. Rozwój tego rodzaju narz(cid:218)dzi prawdopodobnie przyczyni(cid:239) si(cid:218) do wzrostu popularno(cid:258)ci mikrous(cid:239)ug i vice versa. Architektura mikrous(cid:239)ugowa nap(cid:218)dza rozwój narz(cid:218)dzi do wdra(cid:285)ania aplikacji, a narz(cid:218)dzia te u(cid:239)atwiaj(cid:200) adaptacj(cid:218) architektury mikrous(cid:239)ugowej. Wady mikrous(cid:239)ug mo(cid:285)na podsumowa(cid:202) nast(cid:218)puj(cid:200)co: (cid:81) Nieprzemy(cid:258)lany podzia(cid:239) aplikacji na mikrous(cid:239)ugi mo(cid:285)e by(cid:202) przyczyn(cid:200) problemów z architektur(cid:200) aplikacji. (cid:81) Komunikacja sieciowa pomi(cid:218)dzy mikrous(cid:239)ugami dodatkowo obci(cid:200)(cid:285)a system i jest kolejnym potencjalnym s(cid:239)abym punktem aplikacji. (cid:81) Testowanie i wdra(cid:285)anie mikrous(cid:239)ug mo(cid:285)e by(cid:202) skomplikowanym procesem. (cid:81) Najwi(cid:218)kszym wyzwaniem s(cid:200) trudno(cid:258)ci we wspó(cid:239)dzieleniu danych przez mikrous(cid:239)ugi. Na razie nie przejmuj si(cid:218) zbytnio wadami opisanymi w tej cz(cid:218)(cid:258)ci rozdzia(cid:239)u. Powy(cid:285)sze wnioski mog(cid:200) przyt(cid:239)acza(cid:202), a tradycyjne monolityczne podej(cid:258)cie wydawa(cid:202) si(cid:218) bez- piecznym rozwi(cid:200)zaniem. Jednak w d(cid:239)u(cid:285)szej perspektywie dzi(cid:218)ki podzieleniu aplikacji na mi- krous(cid:239)ugi praca programistów i administratorów b(cid:218)dzie (cid:239)atwiejsza. 28 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Czym s(cid:261) mikrous(cid:225)ugi? Implementacja mikrous(cid:239)ug w j(cid:218)zyku Python Python jest wyj(cid:200)tkowo wszechstronnym j(cid:218)zykiem. Jak zapewne wiesz, jest on wykorzystywany do tworzenia ró(cid:285)nego rodzaju aplikacji, od prostych skryptów systemowych wykonywanych na serwerze po skomplikowane obiektowe aplikacje obs(cid:239)uguj(cid:200)ce miliony u(cid:285)ytkowników. Badania przeprowadzone w 2014 r. przez Philipa Guo, opublikowane na stronie stowarzysze- nia Association for Computing Machinery (ACM), wykaza(cid:239)y, (cid:285)e na ameryka(cid:241)skich uniwersy- tetach Python jest j(cid:218)zykiem znacznie cz(cid:218)(cid:258)ciej wykorzystywanym ni(cid:285) Java i jest najcz(cid:218)(cid:258)ciej stosowany w nauczaniu informatyki. Ten trend jest równie(cid:285) widoczny w bran(cid:285)y rozwoju oprogramowania. Python znajduje si(cid:218) w pierwszej pi(cid:200)tce j(cid:218)zyków w rankingu TIOBE (http://www.tiobe.com/tiobe-index), a w (cid:258)wie- cie aplikacji WWW jest prawdopodobnie jeszcze bardziej popularny, poniewa(cid:285) coraz rzadziej tworzy si(cid:218) aplikacje w j(cid:218)zykach takich jak C. W tej ksi(cid:200)(cid:285)ce przyj(cid:218)te jest za(cid:239)o(cid:285)enie, (cid:285)e znasz j(cid:218)zyk Python. Je(cid:285)eli nie masz jeszcze w tej dziedzinie do- (cid:258)wiadczenia, polecam Ci ksi(cid:200)(cid:285)k(cid:218) Profesjonalne programowanie w Pythonie. Poziom ekspert, z której na- uczysz si(cid:218) zaawansowanych technik programowania w j(cid:218)zyku Python. Niektórzy programi(cid:258)ci maj(cid:200) jednak krytyczn(cid:200) opini(cid:218) o j(cid:218)zyku Python, poniewa(cid:285) nie jest on przystosowany do tworzenia wydajnych us(cid:239)ug WWW, a napisany w nim kod dzia(cid:239)a powoli. Bezsprzecznie kod utworzony w tym j(cid:218)zyku dzia(cid:239)a powoli, niemniej jednak jest to w(cid:239)a(cid:258)ciwy j(cid:218)zyk do tworzenia mikrous(cid:239)ug i wiele du(cid:285)ych firm programistycznych z powodzeniem go w tym celu wykorzystuje. Ta cz(cid:218)(cid:258)(cid:202) rozdzia(cid:239)u zawiera podstawowe informacje o ró(cid:285)nych sposobach kodowania mikro- us(cid:239)ug w j(cid:218)zyku Python, o synchronicznym i asynchronicznym wywo(cid:239)ywaniu procedur oraz kilka szczegó(cid:239)owych uwag dotycz(cid:200)cych wydajno(cid:258)ci kodu. Ta sekcja rozdzia(cid:239)u sk(cid:239)ada si(cid:218) z pi(cid:218)ciu cz(cid:218)(cid:258)ci: (cid:81) Standard WSGI (cid:81) Biblioteki Greenlet i Gevent (cid:81) Platformy Twisted i Tornado (cid:81) Modu(cid:239) asyncio (cid:81) Wydajno(cid:258)(cid:202) kodu Standard WSGI Wi(cid:218)kszo(cid:258)(cid:202) programistów stron WWW znajduje si(cid:218) pod wra(cid:285)eniem (cid:239)atwo(cid:258)ci, z jak(cid:200) tworzy si(cid:218) i uruchamia aplikacje WWW w j(cid:218)zyku Python. 29 Poleć książkęKup książkę Rozwijanie mikrous(cid:225)ug w Pythonie Spo(cid:239)eczno(cid:258)(cid:202) u(cid:285)ytkowników tego j(cid:218)zyka inspirowana standardem CGI (ang. Common Gateway Interface, wspólny interfejs bramowy) opracowa(cid:239)a standard WSGI (ang. Web Server Gateway Interface, interfejs bramowy serwera WWW), który znacznie upro(cid:258)ci(cid:239) tworzenie aplikacji ob- s(cid:239)uguj(cid:200)cych zapytania HTTP. Kod wykorzystuj(cid:200)cy ten standard mo(cid:285)na uruchamia(cid:202) na serwe- rach WWW takich jak Apache lub Nginx wyposa(cid:285)onych w rozszerzenia uwsgi lub mod_wsgi. Aplikacja WWW musi równie(cid:285) odbiera(cid:202) (cid:285)(cid:200)dania i wysy(cid:239)a(cid:202) odpowiedzi w formacie JSON. Operacje te s(cid:200) zaimplementowane w standardowej bibliotece j(cid:218)zyka Python. Kod w pe(cid:239)ni funkcjonalnej mikrous(cid:239)ugi zwracaj(cid:200)cej lokalny czas serwera, wykorzystuj(cid:200)cy zwyk(cid:239)e biblioteki Python, sk(cid:239)ada si(cid:218) z nieca(cid:239)ych 10 wierszy (patrz ni(cid:285)ej: import json import time def application(environ, start_response): headers = [( Content-type , application/json )] start_response( 200 OK , headers) return [bytes(json.dumps({ time : time.time()}), utf8 )] Interfejs WSGI ju(cid:285) od momentu opracowania sta(cid:239) si(cid:218) podstawowym standardem szeroko sto- sowanym przez spo(cid:239)eczno(cid:258)(cid:202) u(cid:285)ytkowników j(cid:218)zyka Python. Programi(cid:258)ci wykorzystuj(cid:200) go do tworzenia oprogramowania po(cid:258)rednicz(cid:200)cego i oferuj(cid:200)cego funkcje, które mog(cid:200) by(cid:202) wykorzy- stywane przez aplikacje do realizowania ró(cid:285)nych operacji w swoich (cid:258)rodowiskach. Niektóre platformy do tworzenia stron WWW, np. Bottle (http://bottlepy.org), zosta(cid:239)y specjal- nie oparte na tym standardzie i wkrótce za pomoc(cid:200) interfejsu WSGI b(cid:218)dzie mo(cid:285)na korzysta(cid:202) ze wszystkich platform. Mankamentem interfejsu WSGI jest jednak jego synchroniczna natura. Funkcj(cid:218) w powy(cid:285)- szym kodzie mo(cid:285)na wywo(cid:239)ywa(cid:202) dok(cid:239)adnie tylko raz po odebraniu zapytania, a odpowied(cid:283) na nie mo(cid:285)na wys(cid:239)a(cid:202) dopiero wtedy, gdy funkcja zako(cid:241)czy dzia(cid:239)anie. Oznacza to, (cid:285)e przy ka(cid:285)dym wywo(cid:239)aniu tej funkcji wykonywanie g(cid:239)ównego kodu aplikacji jest wstrzymywane do czasu, a(cid:285) funkcja zwróci wynik. W podej(cid:258)ciu mikrous(cid:239)ugowym kod musi ca(cid:239)y czas oczekiwa(cid:202) na odpowiedzi od ró(cid:285)nych zaso- bów sieciowych. Innymi s(cid:239)owy, aplikacja pozostaje bezczynna i blokuje obs(cid:239)ug(cid:218) u(cid:285)ytkownika do czasu przygotowania pe(cid:239)nej odpowiedzi. Jest to zupe(cid:239)nie poprawne podej(cid:258)cie w przypadku interfejsu HTTP API. Nie mówimy tu o aplikacjach realizuj(cid:200)cych dwukierunkow(cid:200) komunikacj(cid:218), opart(cid:200) na przyk(cid:239)ad na gniazdach sieciowych. Co si(cid:218) jednak stanie, gdy aplikacja odbierze kilka zapyta(cid:241) jednocze(cid:258)nie? Serwer WSGI pozwala uruchamia(cid:202) kilka w(cid:200)tków jednocze(cid:258)nie, co umo(cid:285)liwia równoleg(cid:239)e ob- s(cid:239)ugiwanie zapyta(cid:241). Ale nie mo(cid:285)na uruchamia(cid:202) tysi(cid:218)cy w(cid:200)tków, poniewa(cid:285) ich pula si(cid:218) wy- czerpie i kolejne zapytanie zostanie wstrzymane, mimo (cid:285)e mikrous(cid:239)uga nie wykonuje (cid:285)adnych 30 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Czym s(cid:261) mikrous(cid:225)ugi? operacji i czeka na odpowied(cid:283) innej us(cid:239)ugi w tle. Ten problem jest jedn(cid:200) z przyczyn ogromnej popularno(cid:258)ci platform, które nie wykorzystuj(cid:200) standardu WSGI. S(cid:200) to w pe(cid:239)ni asynchronicz- ne platformy Twisted i Tornado, a w (cid:258)wiecie JavaScript jest to Node.js. W kodzie opartym na platformie Twisted wykorzystywane s(cid:200) funkcje zwrotne wstrzymuj(cid:200)ce i wznawiaj(cid:200)ce prac(cid:218) podczas przygotowywania odpowiedzi na zapytanie. Oznacza to, (cid:285)e apli- kacja mo(cid:285)e odbiera(cid:202) i przetwarza(cid:202) kolejne zapytania. Ten model radykalnie skraca okresy bezczynno(cid:258)ci procesu, a aplikacja mo(cid:285)e obs(cid:239)ugiwa(cid:202) tysi(cid:200)ce jednoczesnych zapyta(cid:241). Oczywi- (cid:258)cie, nie oznacza to, (cid:285)e szybciej wtedy odpowiada na zapytania, ale (cid:285)e jeden proces mo(cid:285)e od- biera(cid:202) wi(cid:218)cej jednoczesnych zapyta(cid:241) i odpowiada(cid:202) na nie w miar(cid:218) otrzymywania niezb(cid:218)d- nych danych. Nie istnieje jeden prosty sposób zaimplementowania podobnej funkcjonalno(cid:258)ci z wykorzysta- niem standardu WSGI. Spo(cid:239)eczno(cid:258)(cid:202) programistów bez powodzenia debatowa(cid:239)a latami nad znalezieniem konsensusu. Prawdopodobnie standard ten zostanie ostatecznie porzucony na rzecz jakiego(cid:258) innego rozwi(cid:200)zania. Na razie wci(cid:200)(cid:285) mo(cid:285)na tworzy(cid:202) mikrous(cid:239)ugi wykorzystuj(cid:200)ce platformy synchroniczne. Jest to ca(cid:239)kowicie poprawne podej(cid:258)cie, je(cid:285)eli aplikacja dopuszcza warunek jedno zapytanie = jeden w(cid:200)tek, typowy dla standardu WSGI. Mo(cid:285)na jednak zastosowa(cid:202) pewn(cid:200) sztuczk(cid:218) przyspieszaj(cid:200)c(cid:200) dzia(cid:239)anie aplikacji synchronicz- nych: u(cid:285)y(cid:202) biblioteki Greenlet opisanej w nast(cid:218)pnej cz(cid:218)(cid:258)ci rozdzia(cid:239)u. Biblioteki Greenlet i Gevent Podstawow(cid:200) zasad(cid:200) programowania asynchronicznego jest symulowanie równoleg(cid:239)o(cid:258)ci proce- sów poprzez uruchamianie ich w wielu kontekstach jednocze(cid:258)nie. Aplikacja asynchroniczna wykorzystuje p(cid:218)tl(cid:218) zdarze(cid:241), która wstrzymuje i wznawia konteksty wykonawcze, gdy pojawi si(cid:218) jakie(cid:258) zdarzenie. W danej chwili aktywny mo(cid:285)e by(cid:202) tylko jeden kontekst. Jawne instrukcje w kodzie okre(cid:258)laj(cid:200), kiedy p(cid:218)tla ma wstrzyma(cid:202) dzia(cid:239)anie i proces mo- (cid:285)e podj(cid:200)(cid:202) zawieszone wcze(cid:258)niej zadania. Przechodzenie z jednego kontekstu wykonawczego do innego nosi nazw(cid:218) prze(cid:239)(cid:200)czania kontekstów. Biblioteka Greenlet (https://github.com/python-greenlet/greenlet) jest pakietem utworzonym w j(cid:218)zyku Stackless (szczególnej implementacji CPython) oferuj(cid:200)cym tzw. greenlety. Greenlety s(cid:200) to pseudow(cid:200)tki, których instancje — w odró(cid:285)nieniu od prawdziwych w(cid:200)tków — tworzy si(cid:218) bardzo (cid:239)atwo i które mo(cid:285)na wykorzystywa(cid:202) do wywo(cid:239)ywania funkcji w j(cid:218)zyku Python. Funkcje te mog(cid:200) prze(cid:239)(cid:200)cza(cid:202) konteksty i przekazywa(cid:202) sterowanie innym funkcjom. Prze(cid:239)(cid:200)czanie odbywa si(cid:218) w p(cid:218)tli zdarze(cid:241). W ten sposób mo(cid:285)na tworzy(cid:202) asynchroniczne aplikacje podobne do aplikacji wielow(cid:200)tkowych. 31 Poleć książkęKup książkę Rozwijanie mikrous(cid:225)ug w Pythonie Poni(cid:285)ej przedstawiony jest przyk(cid:239)adowy kod z dokumentacji biblioteki Greenlet: from greenlet import greenlet def test1(x, y): z = gr2.switch(x+y) print(z) def test2(u): print (u) gr1.switch(42) gr1 = greenlet(test1) gr2 = greenlet(test2) gr1.switch( Witaj, , (cid:258)wiecie! ) Ten kod jawnie prze(cid:239)(cid:200)cza mi(cid:218)dzy sob(cid:200) dwa greenlety. Kod mikrous(cid:239)ugi wykorzystuj(cid:200)cy standard WSGI i greenlety mo(cid:285)e obs(cid:239)ugiwa(cid:202) wiele (cid:285)(cid:200)da(cid:241) jed- nocze(cid:258)nie i prze(cid:239)(cid:200)cza(cid:202) si(cid:218) pomi(cid:218)dzy nimi, podobnie jak w przypadku zapyta(cid:241) wej(cid:258)cia/wyj(cid:258)cia, je(cid:285)eli obs(cid:239)uga którego(cid:258) z zapyta(cid:241) zostanie zablokowana. Jednak prze(cid:239)(cid:200)czanie pomi(cid:218)dzy greenletami musi odbywa(cid:202) si(cid:218) jawnie, a to powoduje, (cid:285)e kod szybko si(cid:218) komplikuje i staje si(cid:218) nieczytelny. W tym momencie bardzo przydaje si(cid:218) bi- blioteka Gevent. Biblioteka Gevent (http://www.gevent.org) jest oparta na bibliotece Greenlet i oferuje mi(cid:218)dzy innymi mo(cid:285)liwo(cid:258)(cid:202) automatycznego prze(cid:239)(cid:200)czania kodu mi(cid:218)dzy greenletami. Oferuje równie(cid:285) specjalny modu(cid:239) socket wykorzystuj(cid:200)cy greenlety do automatycznego wstrzymywania i wzna- wiania kodu, gdy w gnie(cid:283)dzie pojawi(cid:200) si(cid:218) dane. Dost(cid:218)pna jest równie(cid:285) funkcjonalno(cid:258)(cid:202) auto- matycznego zast(cid:218)powania standardowego gniazda jego analogiczn(cid:200) wersj(cid:200). Po wpisaniu jednego dodatkowego wiersza wykorzystuj(cid:200)cy gniazda kod synchroniczny w magiczny sposób zamie- nia si(cid:218) w kod asynchroniczny (jak poni(cid:285)ej): from gevent import monkey; monkey.patch_all() def application(environ, start_response): headers = [( Content-type , application/json )] start_response( 200 OK , headers) # ...Kod obs(cid:225)uguj(cid:261)cy gniazdo... return result Ta magia ma jednak swoj(cid:200) cen(cid:218). Aby biblioteka Gevent dzia(cid:239)a(cid:239)a poprawnie, ca(cid:239)y wykorzystu- j(cid:200)cy j(cid:200) kod musi by(cid:202) kompatybilny z jej wersj(cid:200). Z tego powodu niektóre pakiety rozwijane przez spo(cid:239)eczno(cid:258)(cid:202) programistów blokuj(cid:200) si(cid:218), a nawet zwracaj(cid:200) nieoczekiwane wyniki. Dotyczy to w szczególno(cid:258)ci pakietów wykorzystuj(cid:200)cych rozszerzenia w j(cid:218)zyku C omijaj(cid:200)ce standardowe funkcjonalno(cid:258)ci biblioteki Gevent. Jednak w wi(cid:218)kszo(cid:258)ci przypadków biblioteka ta dzia(cid:239)a poprawnie. Projekty na niej oparte s(cid:200) oznaczane jako zielone. Je(cid:258)li biblioteka nie dzia(cid:239)a poprawnie, wtedy zazwyczaj autor popra- wia j(cid:200) na (cid:285)yczenie spo(cid:239)eczno(cid:258)ci u(cid:285)ytkowników. Tak by(cid:239)o na przyk(cid:239)ad w przypadku skalowania us(cid:239)ugi Firefox Sync w Mozilli. 32 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Czym s(cid:261) mikrous(cid:225)ugi? Platformy Twisted i Tornado Je(cid:285)eli tworzysz aplikacj(cid:218) z(cid:239)o(cid:285)on(cid:200) z mikrous(cid:239)ug i wa(cid:285)n(cid:200) kwesti(cid:200) jest du(cid:285)a liczba jednoczesnych zapy- ta(cid:241) do obs(cid:239)u(cid:285)enia, warto rozwa(cid:285)y(cid:202) odej(cid:258)cie od standardu WSGI na rzecz asynchronicznej platformy, na przyk(cid:239)ad Tornado (http://www.tornadoweb.org) lub Twisted (https://twistedmatrix.com/trac). Platforma Twisted istnieje od dawna. Kod implementuj(cid:200)cy t(cid:218) sam(cid:200) mikrous(cid:239)ug(cid:218) co poprzednio jest nieco bardziej rozbudowany (jak poni(cid:285)ej): import time import json from twisted.web import server, resource from twisted.internet import reactor, endpoints class Simple(resource.Resource): isLeaf = True def render_GET(self, request): request.responseHeaders.addRawHeader(b content-type , b application/json ) return bytes(json.dumps({ time : time.time()}), utf8 ) site = server.Site(Simple()) endpoint = endpoints.TCP4ServerEndpoint(reactor, 8080) endpoint.listen(site) reactor.run() Platforma Twisted jest wyj(cid:200)tkowo spójna i wydajna, jednak ma kilka mankamentów ujawnia- j(cid:200)cych si(cid:218) podczas tworzenia aplikacji WWW, m.in.: (cid:81) Ka(cid:285)dy punkt ko(cid:241)cowy mikrous(cid:239)ugi trzeba implementowa(cid:202) za pomoc(cid:200) klasy pochodnej od Resource i kodowa(cid:202) wszystkie jej metody. W przypadku prostej mikrous(cid:239)ugi trzeba z tego powodu napisa(cid:202) mnóstwo zb(cid:218)dnego kodu interfejsu API. (cid:81) Kod wykorzystuj(cid:200)cy t(cid:218) platform(cid:218) jest ma(cid:239)o czytelny i trudny w diagnozowaniu ze wzgl(cid:218)du na jego asynchroniczn(cid:200) natur(cid:218). (cid:81) W przypadku d(cid:239)ugiego (cid:239)a(cid:241)cucha funkcji zwrotnych wywo(cid:239)ywanych jedna po drugiej (cid:239)atwo jest wpa(cid:258)(cid:202) w tzw. piek(cid:239)o wywo(cid:239)a(cid:241) zwrotnych, a ponadto kod staje si(cid:218) zagmatwany. (cid:81) Trudno jest przetestowa(cid:202) aplikacj(cid:218) i do tego celu trzeba u(cid:285)ywa(cid:202) specjalnego modu(cid:239)u do testów jednostkowych. Platforma Tornado jest oparta na podobnym modelu, jednak w niektórych obszarach spraw- dza si(cid:218) lepiej. Jest wyposa(cid:285)ona w lepszy system kierowania zapyta(cid:241), a jej kod jest bardziej podobny do zwyk(cid:239)ego kodu Python. Platforma Tornado wykorzystuje jednak model wywo(cid:239)a(cid:241) zwrotnych, co utrudnia diagnostyk(cid:218) kodu. Jednak zespo(cid:239)y rozwijaj(cid:200)ce obie platformy intensywnie pracuj(cid:200) nad usuni(cid:218)ciem niedoskona- (cid:239)o(cid:258)ci, aby mo(cid:285)na by(cid:239)o korzysta(cid:202) z funkcjonalno(cid:258)ci asynchronicznych wprowadzonych w j(cid:218)zyku Python 3. 33 Poleć książkęKup książkę Rozwijanie mikrous(cid:225)ug w Pythonie Modu(cid:239) asyncio Gdy Guido van Rossum rozpocz(cid:200)(cid:239) prac(cid:218) nad wzbogaceniem j(cid:218)zyka Python 3 o asynchronicz- no(cid:258)(cid:202), cz(cid:218)(cid:258)(cid:202) spo(cid:239)eczno(cid:258)ci u(cid:285)ytkowników zacz(cid:218)(cid:239)a nawo(cid:239)ywa(cid:202) do stosowania rozwi(cid:200)za(cid:241) takich jak biblioteka Gevent, poniewa(cid:285) o wiele rozs(cid:200)dniej by(cid:239)o tworzy(cid:202) aplikacje dzia(cid:239)aj(cid:200)ce w syn- chroniczny, sekwencyjny sposób, ni(cid:285) stosowa(cid:202) jawne wywo(cid:239)ania zwrotne, jak w bibliotekach Tornado i Twisted. Guido zdecydowa(cid:239) si(cid:218) jednak na jawn(cid:200) technik(cid:218) i rozpocz(cid:200)(cid:239) eksperymentalny projekt Tulip inspirowany platform(cid:200) Twisted. W ten sposób powsta(cid:239) modu(cid:239) asyncio, który zosta(cid:239) dodany do j(cid:218)zyka Python. Patrz(cid:200)c z perspektywy czasu, implementacja jawnej p(cid:218)tli zdarze(cid:241) jest znacznie lepszym roz- wi(cid:200)zaniem od mechanizmu oferowanego przez bibliotek(cid:218) Gevent. Sposób zakodowania przez twórców j(cid:218)zyka Python modu(cid:239)u asyncio i eleganckie rozszerzenie go o instrukcje async i await implementuj(cid:200)ce koprocedury sprawi(cid:239)y, (cid:285)e asynchroniczny kod napisany w podstawowym j(cid:218)zyku Python 3.5 jest bardzo czytelny i podobny do kodu synchronicznego. Koprocedury s(cid:200) to funkcje wstrzymuj(cid:200)ce i wznawiaj(cid:200)ce swoje dzia(cid:239)anie. Rozdzia(cid:239) 12, „Co dalej?” szcze- gó(cid:239)owo opisuje ich implementacj(cid:218) i wykorzystanie w kodzie Python. Dzi(cid:218)ki temu doskona(cid:239)emu rozwi(cid:200)zaniu mo(cid:285)na unikn(cid:200)(cid:202) ba(cid:239)aganu w asynchronicznym kodzie, jaki czasami pojawia si(cid:218) w aplikacjach opartych na platformach Node.js lub Twisted (Python 2). Oprócz koprocedur modu(cid:239) asyncio oferuje pe(cid:239)ny zestaw funkcji i klas pomocniczych do tworzenia apli- kacji asynchronicznych. Ich opis jest dost(cid:218)pny na stronie https://docs.python.org/3/library/asyncio.html. Obecnie Python jest równie ekspresyjnym j(cid:218)zykiem jak Lua, umo(cid:285)liwiaj(cid:200)cym tworzenie apli- kacji opartych na koprocedurach. Ponadto pojawi(cid:239)o si(cid:218) kilka platform wykorzystuj(cid:200)cych nowe funkcjonalno(cid:258)ci, z których mo(cid:285)na korzysta(cid:202) tylko w wersji j(cid:218)zyka Python 3.5 lub nowszej. Jedn(cid:200) z nich jest aiohttp (http://aiohttp.readthedocs.io). W pe(cid:239)ni asynchroniczny kod tej samej mikrous(cid:239)ugi co poprzednio sk(cid:239)ada si(cid:218) zaledwie z kilku eleganckich wierszy: from aiohttp import web import time async def handle(request): return web.json_response({ time : time.time()}) if __name__ == __main__ : app = web.Application() app.router.add_get( / , handle) web.run_app(app) Ten krótki kod jest bardzo podobny do swojej synchronicznej wersji. Jedyn(cid:200) ró(cid:285)nic(cid:200) jest s(cid:239)owo kluczowe async definiuj(cid:200)ce funkcj(cid:218) jako koprocedur(cid:218). 34 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Czym s(cid:261) mikrous(cid:225)ugi? W ten w(cid:239)a(cid:258)nie sposób nale(cid:285)y kodowa(cid:202) w j(cid:218)zyku Python ka(cid:285)d(cid:200) asynchroniczn(cid:200) aplikacj(cid:218). Poni(cid:285)ej przedstawiony jest przyk(cid:239)adowy kod z dokumentacji projektu, wykorzystuj(cid:200)cy biblioteki aiopg i asyncio do obs(cid:
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Rozwijanie mikrousług w Pythonie. Budowa, testowanie, instalacja i skalowanie
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ą: