Cyfroteka.pl

klikaj i czytaj online

Cyfro
Czytomierz
00191 001156 12922066 na godz. na dobę w sumie
Node.js. Projektowanie, wdrażanie i utrzymywanie aplikacji - ebook/pdf
Node.js. Projektowanie, wdrażanie i utrzymywanie aplikacji - ebook/pdf
Autor: Liczba stron: 232
Wydawca: Helion Język publikacji: polski
ISBN: 978-83-283-3610-0 Data wydania:
Lektor:
Kategoria: ebooki >> komputery i informatyka >> webmasterstwo >> javascript - programowanie
Porównaj ceny (książka, ebook (-40%), audiobook).

W ciągu kilku ostatnich lat JavaScript stał się niezwykle wszechstronnym i wydajnym językiem programowania. Dla programistów kodujących w tym języku świetnym narzędziem okazuje się platforma Node.js. Ten framework open source został zaprojektowany do tworzenia skalowalnych aplikacji internetowych, jednak umożliwia też tworzenie aplikacji sterowanych zdarzeniami. Użytkownicy docenili jego wygodę. Node.js odniósł spory sukces i stał się kluczowym narzędziem programistycznym w wielu firmach. Mimo to odnalezienie wyczerpujących informacji o profesjonalnym projektowaniu, testowaniu i wdrażaniu oprogramowania za jego pomocą jest dość trudne.

Niniejsza książka zawiera opis technik i narzędzi pozwalających na wykonanie w Node.js elastycznej, inteligentnej, trwałej i łatwej w utrzymaniu aplikacji o znakomitej jakości. Poza podstawami zaprezentowano tu również zestaw wzorców ułatwiających rozwiązywanie typowych problemów pojawiających się w dzisiejszych projektach. Nie zabrakło licznych przykładów z życia oraz wskazówek, które doceni każdy, kto musi sprawnie wdrożyć trudny projekt. Książka umożliwia zgłębienie tajników Node.js i naukę projektowania modułowego. Sporo miejsca poświęcono też testowaniu i monitorowaniu aplikacji oraz strategiom utrzymania aplikacji przez większy zespół.

Najważniejsze zagadnienia:

Node.js: dojrzała technologia, znakomita wydajność i wszechstronność!


Sandro Pasquali — programista, przedsiębiorca, twórca firmy technologicznej Simple.com, która sprzedawała pierwszy na świecie framework aplikacyjny oparty na języku JavaScript. Obecnie autor szkoli zespoły programistów korporacyjnych. W swoim czasie zarządzał projektowaniem wielu aplikacji dla takich firm jak Nintendo, Major League Baseball, LimeWire, AppNexus i Conde Nast, a także dla instytutów badawczych i szkół. Zawsze szuka nowych sposobów na połączenie doskonałości projektowej z innowacyjną technologią.

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

Darmowy fragment publikacji:

Tytuł oryginału: Deploying Node.js Tłumaczenie: Rafał Jońca ISBN: 978-83-283-3609-4 Copyright © Packt Publishing 2015. First published in the English language under the title ‘Deploying Node.js – (9781783981403)’. Polish edition copyright © 2017 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 Wydawnictwo HELION 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 Wydawnictwo HELION nie ponoszą również żadnej odpowiedzialności za ewentualne szkody wynikłe z wykorzystania informacji zawartych w książce. Wydawnictwo HELION 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/nodepr Możesz tam wpisać swoje uwagi, spostrzeżenia, recenzję. Printed in Poland. • Kup książkę • Poleć książkę • Oceń książkę • Księgarnia internetowa • Lubię to! » Nasza społeczność Spis tre(cid:258)ci O autorze O redaktorach merytorycznych Wst(cid:218)p Zawarto(cid:258)(cid:202) ksi(cid:200)(cid:285)ki Narz(cid:218)dzia potrzebne do realizacji przyk(cid:239)adów Do kogo kierowana jest ksi(cid:200)(cid:285)ka? Konwencje typograficzne Przyk(cid:239)adowy kod Rozdzia(cid:239) 1. Doceni(cid:202) Node Unikatowo zaprojektowany Node Wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) Równoleg(cid:239)o(cid:258)(cid:202) i w(cid:200)tki Wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) i procesy Zdarzenia P(cid:218)tla zdarze(cid:241) Wp(cid:239)yw sposobu zaprojektowania Node na architektów systemów Budowanie wi(cid:218)kszych systemów z mniejszych Strumienie Wykorzystanie JavaScript na ka(cid:285)dym etapie projektu maksymalizuje dobre efekty Zamiana kodu Browserify Podsumowanie Rozdzia(cid:239) 2. Instalacja i wirtualizacja serwerów Node Uruchamianie podstawowego serwera Node Witaj, (cid:258)wiecie Tworzenie (cid:285)(cid:200)da(cid:241) HTTP Po(cid:258)redniczenie i tunelowanie 9 11 13 14 15 15 16 16 17 18 20 21 23 24 26 30 30 32 33 34 34 35 37 38 38 39 40 Poleć książkęKup książkę Node.js. Projektowanie, wdra(cid:298)anie i utrzymywanie aplikacji HTTPS, TLS (SSL) i zabezpieczanie serwera Tworzenie podpisanego samodzielnie certyfikatu na potrzeby programistyczne Instalacja prawdziwego certyfikatu SSL Instalacja aplikacji w chmurze Heroku Dodatki Git Zarz(cid:200)dzanie zmiennymi konfiguracyjnymi Zarz(cid:200)dzanie wdro(cid:285)eniem Instalacja aplikacji w chmurze OpenShift Instalacja aplikacji Node i MongoDB Wdro(cid:285)enie aplikacji Docker, czyli lekkie i wirtualne kontenery Najpierw jednak (cid:239)yk systemu Unix Korzystanie z systemu Docker Tworzenie pliku Dockerfile Zbudowanie i uruchomienie obrazu Dockera Podsumowanie Rozdzia(cid:239) 3. Skalowanie Node Skalowanie pionowe wykorzystuj(cid:200)ce wiele rdzeni procesora Funkcja spawn() Funkcja fork() Funkcja exec() Funkcja execFile() Komunikacja z procesem potomnym Modu(cid:239) cluster Skalowanie w poziomie z wykorzystaniem wielu maszyn U(cid:285)ycie serwera Nginx Równowa(cid:285)enie obci(cid:200)(cid:285)enia za pomoc(cid:200) Node U(cid:285)ycie kolejek komunikatów U(cid:285)ycie modu(cid:239)u komunikacji UDP serwera Node Podsumowanie Rozdzia(cid:239) 4. Zarz(cid:200)dzanie pami(cid:218)ci(cid:200) i przestrzeni(cid:200) Jak poradzi(cid:202) sobie z du(cid:285)ym t(cid:239)umem? Mikroserwisy Mechanizm pub-sub serwera Redis Mikroserwisy w narz(cid:218)dziu Seneca Zmniejszenie zu(cid:285)ycia pami(cid:218)ci U(cid:285)ywaj strumieni zamiast buforów Prototypy Wydajne pami(cid:218)ciowo struktury danych z wykorzystaniem serwera Redis V8 i optymalizacja wydajno(cid:258)ci Optymalizacja kodu JavaScript Strategie dotycz(cid:200)ce pami(cid:218)ci podr(cid:218)cznych Wykorzystanie Redis jako pami(cid:218)ci podr(cid:218)cznej Wdra(cid:285)anie CloudFlare jako CDN 4 42 42 43 44 46 46 49 50 51 52 52 54 56 57 58 59 61 63 64 65 68 70 71 71 73 77 77 85 87 91 96 97 98 98 99 102 105 106 107 109 116 116 121 121 125 Poleć książkęKup książkę Spis tre(cid:286)ci Zarz(cid:200)dzanie sesj(cid:200) u(cid:285)ytkownika Uwierzytelnianie i sesje JWT Podsumowanie Rozdzia(cid:239) 5. Monitorowanie aplikacji Jak poradzi(cid:202) sobie z b(cid:239)(cid:218)dami? Modu(cid:239) domain Wy(cid:239)apywanie b(cid:239)(cid:218)dów innych procesów Tworzenie dzienników zdarze(cid:241) Dostosowywanie dzia(cid:239)ania w zmieniaj(cid:200)cym si(cid:218) (cid:258)rodowisku REPL narz(cid:218)dzia Node Zdalny monitoring i zarz(cid:200)dzanie procesem Node Profilowanie procesów Wykorzystywanie niezale(cid:285)nych narz(cid:218)dzi do monitorowania PM2 Wykorzystanie New Relic do monitorowania aplikacji Podsumowanie Rozdzia(cid:239) 6. Budowanie i testowanie Budowanie aplikacji za pomoc(cid:200) narz(cid:218)dzi Gulp, Browserify i Handlebars Narz(cid:218)dzie Gulp Wykonanie szkieletu systemu budowania Uruchamianie i testowanie zbudowanej wersji Wykorzystanie narz(cid:218)dzi do testowania wbudowanych w system Node Debuger wbudowany w system Node Modu(cid:239) assert Testowanie za pomoc(cid:200) Mocha, Chai, Sinon i npm Mocha Chai Sinon Automatyzacja testów w przegl(cid:200)darce internetowej dzi(cid:218)ki PhantomJS i CasperJS Testowanie z wykorzystaniem PhantomJS Scenariusze nawigacyjne w CasperJS Podsumowanie Rozdzia(cid:239) 7. Wdra(cid:285)anie i konserwacja GitHub i mechanizm webhook W(cid:239)(cid:200)czenie mechanizmu webhook Implementacja systemu budowania i wdra(cid:285)ania wykorzystuj(cid:200)cego mechanizm webhook Synchronizacja wersji lokalnej i zdalnej Tworzenie wersji lokalnej za pomoc(cid:200) narz(cid:218)dzia Vagrant Przygotowywanie systemu przy u(cid:285)yciu Ansible Integracja, dostarczanie i wdra(cid:285)anie Ci(cid:200)g(cid:239)a integracja Ci(cid:200)g(cid:239)e dostarczanie 127 127 131 133 134 135 137 140 144 144 146 149 152 152 156 158 159 160 160 163 169 171 172 175 177 178 180 181 187 187 189 192 193 194 195 198 201 201 205 208 208 208 5 Poleć książkęKup książkę Node.js. Projektowanie, wdra(cid:298)anie i utrzymywanie aplikacji Ci(cid:200)g(cid:239)e wdra(cid:285)anie Budowanie i wdra(cid:285)anie z u(cid:285)yciem narz(cid:218)dzia Jenkins Wdra(cid:285)anie w chmurze Heroku Zarz(cid:200)dzanie pakietami Wersjonowanie semantyczne Zarz(cid:200)dzanie pakietami z u(cid:285)yciem npm Skorowidz 209 209 213 216 216 218 225 6 Poleć książkęKup książkę 1 Doceni(cid:202) Node Node istnieje ju(cid:285) ponad siedem lat i ka(cid:285)dego roku wykorzystuje si(cid:218) go coraz intensywniej. W zasadzie mo(cid:285)na powiedzie(cid:202), (cid:285)e nie istnieje ju(cid:285) ryzyko, (cid:285)e Node pojawi si(cid:218) jak gwiazda pop i równie szybko zniknie. Node to naprawd(cid:218) powa(cid:285)na technologia budowana przez bardzo uzdolniony zespó(cid:239) g(cid:239)ówny i wspomagana przez aktywn(cid:200) spo(cid:239)eczno(cid:258)(cid:202), która ca(cid:239)y czas czuwa nad popraw(cid:200) szybko(cid:258)ci dzia(cid:239)ania, bezpiecze(cid:241)stwa i u(cid:285)yteczno(cid:258)ci. Ka(cid:285)dego dnia programi(cid:258)ci napotykaj(cid:200) problemy, które Node stara si(cid:218) rozwi(cid:200)za(cid:202). Oto kilka z nich: (cid:81) skalowanie aplikacji sieciowych jako rozwi(cid:200)za(cid:241) z wieloma serwerami; (cid:81) zapobieganie w(cid:200)skim gard(cid:239)om w komunikacji wej(cid:258)cie-wyj(cid:258)cie (baza danych, plik, komunikacja sieciowa); (cid:81) monitorowanie systemów i sprawdzanie ich wydajno(cid:258)ci; (cid:81) testowanie integralno(cid:258)ci komponentów systemu; (cid:81) bezpieczne zarz(cid:200)dzanie wspó(cid:239)bie(cid:285)no(cid:258)ci(cid:200); (cid:81) (cid:239)atwe umieszczanie zmian w kodzie w (cid:258)rodowiskach produkcyjnych. W tej ksi(cid:200)(cid:285)ce omawiamy techniki zwi(cid:200)zane z wdra(cid:285)aniem, skalowaniem, monitorowaniem, testo- waniem i utrzymaniem aplikacji Node. Skupimy si(cid:218) na g(cid:239)ównej cesze wyró(cid:285)niaj(cid:200)cej Node, czyli modelu nieblokuj(cid:200)cym sterowanym zdarzeniami i jego efektywnym wykorzystaniu do realizacji w(cid:239)asnych zada(cid:241). W dniu 28 lutego 2014 roku Eran Hammer wyg(cid:239)osi(cid:239) wyk(cid:239)ad otwieraj(cid:200)cy NodeDay, du(cid:285)(cid:200) konfe- rencj(cid:218) dla programistów sponsorowan(cid:200) przez firm(cid:218) PayPal. Zacz(cid:200)(cid:239) od wymienienia kilku liczb istotnych dla jego pracodawcy, firmy Walmart: (cid:81) 11 000 sklepów; (cid:81) ponad trylion dolarów sprzeda(cid:285)y ka(cid:285)dego roku; (cid:81) ponad 2 miliony pracowników; (cid:81) najwi(cid:218)kszy prywatny pracodawca na (cid:258)wiecie. Poleć książkęKup książkę Node.js. Projektowanie, wdra(cid:298)anie i utrzymywanie aplikacji Nast(cid:218)pnie powiedzia(cid:239): 55 ruchu w czarny pi(cid:200)tek, czyli naszym szczycie sezonu, ka(cid:285)dego roku powoduje realizacj(cid:218) oko(cid:239)o 40 rocznych przychodów. 55 tego ruchu pochodzi z urz(cid:200)dze(cid:241) przeno(cid:258)nych… 55 ruchu przechodzi(cid:239)o w 100 poprzez serwery Node. (…) Uda(cid:239)o nam si(cid:218) ud(cid:283)wign(cid:200)(cid:202) ten ogromny ruch w systemie równowa(cid:285)nym dwóm procesorom i 30 GB RAM. To wszystko. Tylko tyle potrzebowa(cid:239) Node, aby obs(cid:239)u(cid:285)y(cid:202) 100 ruchu mobilnego w czarny pi(cid:200)tek. (…) Walmart to rynek e-commerce warty 10 bilionów dolarów i do ko(cid:241)ca roku te 10 bilionów b(cid:218)dzie przechodzi(cid:239)o w ca(cid:239)o(cid:258)ci przez Node. Eran Hammer, starszy architekt, Walmart Labs Nowoczesne oprogramowanie staje si(cid:218) z ró(cid:285)nych powodów coraz bardziej z(cid:239)o(cid:285)one i w du(cid:285)ej mierze zmienia nasz sposób budowania aplikacji. Wi(cid:218)kszo(cid:258)(cid:202) nowych platform i j(cid:218)zyków stara si(cid:218) w jaki(cid:258) sposób odpowiedzie(cid:202) na t(cid:218) zmian(cid:218). Node nie jest tu wyj(cid:200)tkiem i to samo dotyczy JavaScript jako j(cid:218)zyka. Nauka Node oznacza poznawanie programowania sterowanego zdarzeniami, kompozycj(cid:218) pro- gramu z modu(cid:239)ów, tworzenie i (cid:239)(cid:200)czenie strumieni danych, a tak(cid:285)e produkcj(cid:218) i konsumpcj(cid:218) zdarze(cid:241) i powi(cid:200)zanych z nimi danych. Architektura bazuj(cid:200)ca na Node sk(cid:239)ada si(cid:218) cz(cid:218)sto z wielu ma(cid:239)ych procesów i us(cid:239)ug komunikuj(cid:200)cych si(cid:218) ze sob(cid:200) za pomoc(cid:200) zdarze(cid:241) — wewn(cid:218)trznie za pomoc(cid:200) interfejsu EventEmitter i wywo(cid:239)a(cid:241) zwrotnych, a zewn(cid:218)trznie za pomoc(cid:200) kilku standar- dowych warstw transportowych (np. HTTP i TCP) oraz cienkiej warstwy przekazywania komuni- katów wykorzystuj(cid:200)cej warstw(cid:218) transportow(cid:200) (np. 0MQ, Pub-Sub w Redis lub Kafka). Bardzo cz(cid:218)sto procesy te wykorzystuj(cid:200) kilka bezp(cid:239)atnych, wysokiej jako(cid:258)ci modu(cid:239)ów npm dost(cid:218)pnych na zasadach otwartego kodu (cid:283)ród(cid:239)owego. Ka(cid:285)dy z takich modu(cid:239)ów zawiera testy, dokumentacj(cid:218) lub przyk(cid:239)ady u(cid:285)ycia. W tym rozdziale postaram si(cid:218) przedstawi(cid:202) ogólny zarys Node, wskaza(cid:202) problemy, które stara si(cid:218) rozwi(cid:200)za(cid:202), rozwi(cid:200)zania narzucane przez sposób zaprojektowania Node, a tak(cid:285)e wyja(cid:258)ni(cid:202), co to wszystko oznacza dla programisty. Pokrótce przedstawi(cid:218) te(cid:285) g(cid:239)ówne tematy, które rozwin(cid:218) w dalszych rozdzia(cid:239)ach, na przyk(cid:239)ad odpowiedni(cid:200) struktur(cid:218) zapewniaj(cid:200)c(cid:200) wydajne i stabilne serwery Node, u(cid:285)ycie najlepszych rozwi(cid:200)za(cid:241) JavaScript dla aplikacji i zespo(cid:239)u, a tak(cid:285)e przesta- wienie si(cid:218) na sposób my(cid:258)lenia w kategoriach Node. Zacznijmy od wyja(cid:258)nienia, jak i dlaczego w(cid:239)a(cid:258)nie tak zaprojektowano Node. Unikatowo zaprojektowany Node Operacje wej(cid:258)cia-wyj(cid:258)cia (dysk, sie(cid:202)) s(cid:200) bez w(cid:200)tpienia bardziej kosztowne ni(cid:285) pami(cid:218)(cid:202) operacyj- na. Poni(cid:285)sza tabela przedstawia cykle zegara konsumowane przez typowe zadania systemo- we (warto(cid:258)ci pochodz(cid:200) z prezentacji Ryana Dahla na temat Node — https://www.youtube.com/ watch?v=ztspvPYybIY). 18 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Doceni(cid:252) Node Pami(cid:218)(cid:202) podr(cid:218)czna L1 Pami(cid:218)(cid:202) podr(cid:218)czna L2 RAM Dysk Sie(cid:202) 3 cykle 14 cykli 250 cykli 41 000 000 cykli 240 000 000 cykli Powody wida(cid:202) wyra(cid:283)nie — dysk to urz(cid:200)dzenie fizyczne, cz(cid:218)sto jeszcze w postaci wiruj(cid:200)cych dysków, wi(cid:218)c pobiera dane znacznie wolniej ni(cid:285) urz(cid:200)dzenia czysto pó(cid:239)przewodnikowe (na przy- k(cid:239)ad pami(cid:218)(cid:202) operacyjna) czy dedykowane pami(cid:218)ci podr(cid:218)czne. Podobnie dane nie w(cid:218)druj(cid:200) w sieci z punktu A do punktu B w sposób natychmiastowy. (cid:165)wiat(cid:239)o potrzebuje 0,1344 sekundy, aby okr(cid:200)(cid:285)y(cid:202) kul(cid:218) ziemsk(cid:200)! W sieci u(cid:285)ywanej przez miliony osób wchodz(cid:200)cych ze sob(cid:200) w liczne interakcje szybko(cid:258)(cid:202) przesy(cid:239)ania informacji jest znacznie wolniejsza ni(cid:285) pr(cid:218)dko(cid:258)(cid:202) (cid:258)wiat(cid:239)a, bo nie ma tu wielu linii prostych, a zdarzaj(cid:200) si(cid:218) objazdy i zatory. W efekcie opó(cid:283)nienie wzrasta znacz(cid:200)co. Gdy nasze oprogramowanie dzia(cid:239)a(cid:239)o na komputerach osobistych pod biurkiem, przez sie(cid:202) nie realizowa(cid:239)o si(cid:218) prawie (cid:285)adnej komunikacji. Opó(cid:283)nienia w interakcji z edytorem tekstu lub arku- szem kalkulacyjnym dotyczy(cid:239)y tak naprawd(cid:218) jedynie czasu dost(cid:218)pu do dysku twardego. Ten czas dost(cid:218)pu uda(cid:239)o si(cid:218) znacz(cid:200)co poprawi(cid:202). Po zastosowaniu pami(cid:218)ci podr(cid:218)cznej lub szybszego dysku oprogramowanie wydaje si(cid:218) u(cid:285)ytkownikowi znacznie szybsze. Przyzwyczajeni do tej szybko(cid:258)ci u(cid:285)ytkownicy oczekuj(cid:200) tego samego od innych narz(cid:218)dzi. Pojawienie si(cid:218) rozwi(cid:200)za(cid:241) chmurowych i oprogramowania bazuj(cid:200)cego na przegl(cid:200)darkach interne- towych spowodowa(cid:239)o, (cid:285)e dane opu(cid:258)ci(cid:239)y lokalne dyski i zamieszka(cid:239)y na dyskach zdalnych, a dost(cid:218)p do danych odbywa si(cid:218) poprzez internet. Czasy dost(cid:218)pu do danych znowu uleg(cid:239)y znacznemu wyd(cid:239)u(cid:285)eniu. Sieciowe wej(cid:258)cie-wyj(cid:258)cie jest powolne. Mimo to coraz to wi(cid:218)cej firm migruje fragmenty swoich aplikacji do chmury, a coraz wi(cid:218)cej rozwi(cid:200)za(cid:241) bazuje tylko i wy(cid:239)(cid:200)cznie na wersji sieciowej. Mechanizmy Node zaprojektowano, by przyspieszy(cid:202) komunikacj(cid:218) wej(cid:258)cie-wyj(cid:258)cie, czyli zapro- jektowano je dla nowego, sieciowego (cid:258)wiata, gdzie dane znajduj(cid:200) si(cid:218) w wielu miejscach i musz(cid:200) by(cid:202) szybko sk(cid:239)adane w jedn(cid:200) ca(cid:239)o(cid:258)(cid:202). Wiele tradycyjnych frameworków do budowania aplikacji internetowych powstawa(cid:239)o w czasie, gdy u(cid:285)ytkownik pracowa(cid:239) na swoim komputerze stacjonar- nym i od czasu do czasu wykonywa(cid:239) (cid:285)(cid:200)dania do pojedynczego serwera wykorzystuj(cid:200)cego relacyjn(cid:200) baz(cid:218) danych. Nowoczesne oprogramowanie musi obs(cid:239)ugiwa(cid:202) dziesi(cid:200)tki tysi(cid:218)cy jednoczesnych po(cid:239)(cid:200)cze(cid:241) od klientów i u(cid:285)ywa(cid:202) wielu wspó(cid:239)dzielonych puli danych wykorzystuj(cid:200)cych ró(cid:285)ne protoko(cid:239)y, a sami u(cid:285)ytkownicy komunikuj(cid:200) si(cid:218) z systemem za pomoc(cid:200) ró(cid:285)norakich urz(cid:200)dze(cid:241). Node zaprojektowano z my(cid:258)l(cid:200) o budowaniu tego rodzaju oprogramowania. Co oznacza wspó(cid:239)bie(cid:285)no(cid:258)(cid:202), zrównoleglenie, wykonywanie asynchroniczne, wywo(cid:239)anie zwrotne i zdarzenie dla programisty Node? 19 Poleć książkęKup książkę Node.js. Projektowanie, wdra(cid:298)anie i utrzymywanie aplikacji Wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) Wykonywanie kodu w sposób proceduralny, czyli po kolei, to sensowny pomys(cid:239). Sami tak robimy, wykonuj(cid:200)c zadania w (cid:285)yciu codziennym i przez d(cid:239)ugi czas j(cid:218)zyki programowania by(cid:239)y naturalnie proceduralne. Przecie(cid:285) instrukcje wysy(cid:239)ane do procesora musz(cid:200) by(cid:202) wykonywane w przewidy- walnym porz(cid:200)dku. Je(cid:258)li chc(cid:218) pomno(cid:285)y(cid:202) 8 przez 6 i podzieli(cid:202) ten wynik przez 144 dzielone przez 12, a nast(cid:218)pnie doda(cid:202) do uzyskanego wyniku 10, operacje musz(cid:218) wykona(cid:202) w okre(cid:258)lonej kolejno(cid:258)ci: ( (8*6) / (144/12) ) + 10 Kolejno(cid:258)(cid:202) nie mo(cid:285)e by(cid:202) jak poni(cid:285)sza: (8*6) / ( (144/12) + 10 ) Taki przyk(cid:239)ad (cid:239)atwo zrozumie(cid:202). Pocz(cid:200)tkowo komputery posiada(cid:239)y tylko jeden procesor, a przetwa- rzanie jednej instrukcji blokowa(cid:239)o przetwarzanie nast(cid:218)pnych. Obecnie ta prostota w zasadzie zanik(cid:239)a, bo nawet telefony komórkowe posiadaj(cid:200) procesory wielordzeniowe. Je(cid:258)li przyjrzymy si(cid:218) poprzedniemu przyk(cid:239)adowi, to zauwa(cid:285)ymy, (cid:285)e obliczenie 144/12 i 8×6 mo(cid:285)na realizowa(cid:202) niezale(cid:285)nie — jedno zadanie nie zale(cid:285)y od drugiego. Problem mo(cid:285)na podzie- li(cid:202) na mniejsze i przydzieli(cid:202) je wielu osobom lub procesom wykonawczym, aby realizowa(cid:239)y zadania równolegle. Wynik tych oblicze(cid:241) cz(cid:200)stkowych (cid:239)(cid:200)czy si(cid:218) pó(cid:283)niej w jedn(cid:200) ca(cid:239)o(cid:258)(cid:202), aby otrzyma(cid:202) wynik ostateczny. Wiele procesów, gdy ka(cid:285)dy z nich rozwi(cid:200)zuje symultanicznie jeden problem matematyczny, to przyk(cid:239)ad zrównoleglenia. Rob Pike, wspó(cid:239)twórca j(cid:218)zyka programowania Go (stworzonego w firmie Google), definiuje wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) w nast(cid:218)puj(cid:200)cy sposób: Wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) to takie ustrukturyzowanie rzeczy, aby je(cid:258)li to tylko mo(cid:285)liwe, dopuszczalne by(cid:239)o zrównoleglenie w celu realizacji zadania lepiej lub szybciej. Zrównoleglenie nie jest celem wspó(cid:239)bie(cid:285)no(cid:258)ci; celem wspó(cid:239)bie(cid:285)no(cid:258)ci jest dobra struktura. Wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) to nie zrównoleglenie. System korzystaj(cid:200)cy z zasad wspó(cid:239)bie(cid:285)no(cid:258)ci pozwala programi(cid:258)cie na dekompozycj(cid:218) aplikacji tak, jak gdyby wiele niezale(cid:285)nych procesów wykony- wa(cid:239)o równocze(cid:258)nie wiele zada(cid:241). Udane frameworki zapewniaj(cid:200)ce budowanie systemów o wyso- kiej wspó(cid:239)bie(cid:285)no(cid:258)ci u(cid:239)atwiaj(cid:200) definiowanie w(cid:239)a(cid:258)ciwych rozwi(cid:200)za(cid:241) i wykorzystanie odpowied- niego s(cid:239)ownictwa. Projekt Node sugeruje, (cid:285)e osi(cid:200)gni(cid:218)cie g(cid:239)ównego celu — (cid:239)atwego budowania skalowalnych programów sieciowych — zawiera w sobie uproszczenie wykonywania wspó(cid:239)istniej(cid:200)cych proce- sów i ich kompozycji. Node pomaga programi(cid:258)cie poprawnie wnioskowa(cid:202) na temat programu, w którym wiele rzeczy mo(cid:285)e dzia(cid:202) si(cid:218) jednocze(cid:258)nie (np. obs(cid:239)uga wielu klientów), a tak(cid:285)e lepiej zorganizowa(cid:202) kod. 20 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Doceni(cid:252) Node Przyjrzyjmy si(cid:218) ró(cid:285)nicy mi(cid:218)dzy zrównolegleniem i wspó(cid:239)bie(cid:285)no(cid:258)ci(cid:200), w(cid:200)tkami i procesami, a tak(cid:285)e specjalnemu sposobowi, dzi(cid:218)ki któremu Node stosuje w swoim projekcie najlepsze cz(cid:218)(cid:258)ci ka(cid:285)dego z tych elementów. Równoleg(cid:239)o(cid:258)(cid:202) i w(cid:200)tki Poni(cid:285)szy rysunek przedstawia, w jaki sposób tradycyjny procesor b(cid:218)dzie wykonywa(cid:239) opisany wcze(cid:258)niej program. Program zosta(cid:239) podzielony na poszczególne instrukcje wykonywane w pewnej kolejno(cid:258)ci. Wszyst- ko dzia(cid:239)a, ale wymaga, aby instrukcje by(cid:239)y wykonywane po kolei, czyli gdy przetwarzana jest jedna instrukcja, nast(cid:218)pne musz(cid:200) czeka(cid:202). To proces blokuj(cid:200)cy — wykonywanie jednego segmentu (cid:239)a(cid:241)cucha blokuje pozosta(cid:239)e segmenty. Mówimy o dzia(cid:239)aniu w sposób jednow(cid:200)tkowy. Mam jednak dobr(cid:200) wiadomo(cid:258)(cid:202). Procesor ma (dos(cid:239)ownie) pe(cid:239)n(cid:200) kontrol(cid:218) nad wszystkim, wi(cid:218)c nie ma niebezpiecze(cid:241)stwa, (cid:285)e inny procesor nadpisze mu pami(cid:218)(cid:202) lub zmodyfikuje stan, z którego w(cid:239)a(cid:258)nie korzysta(cid:239). Po(cid:258)wi(cid:218)cili(cid:258)my szybko(cid:258)(cid:202) na rzecz stabilno(cid:258)ci i bezpiecze(cid:241)stwa. Lubimy jednak szybko(cid:258)(cid:202) — przedstawiony model sta(cid:239) si(cid:218) przestarza(cid:239)y, bo projektanci proceso- rów i programi(cid:258)ci systemów wprowadzili systemy z obliczeniami zrównoleglonymi. Zamiast jednego blokuj(cid:200)cego w(cid:200)tku pojawi(cid:239)o si(cid:218) wiele wspó(cid:239)dzia(cid:239)aj(cid:200)cych w(cid:200)tków. To usprawnienie zdecydowanie zwi(cid:218)kszy(cid:239)o szybko(cid:258)(cid:202) oblicze(cid:241), ale wprowadzi(cid:239)o nowe problemy, przedstawione na poni(cid:285)szym rysunku. 21 Poleć książkęKup książkę Node.js. Projektowanie, wdra(cid:298)anie i utrzymywanie aplikacji Rysunek przedstawia wspó(cid:239)dzia(cid:239)aj(cid:200)ce w(cid:200)tki, które dzia(cid:239)aj(cid:200) równolegle wewn(cid:200)trz jednego procesu, co zmniejsza czas niezb(cid:218)dny na realizacj(cid:218) oblicze(cid:241). Poszczególne w(cid:200)tki maj(cid:200) na celu rozbicie zadania, rozwi(cid:200)zanie go i z(cid:239)o(cid:285)enie w jedn(cid:200) ca(cid:239)o(cid:258)(cid:202). Poniewa(cid:285) podzadania mo(cid:285)na realizowa(cid:202) nieza- le(cid:285)nie, (cid:239)(cid:200)czny czas dzia(cid:239)ania mo(cid:285)e ulec znacz(cid:200)cemu skróceniu. W(cid:200)tki zapewniaj(cid:200) zrównoleglenie wewn(cid:200)trz jednego procesu. Ka(cid:285)dy w(cid:200)tek reprezentuje jedn(cid:200) sekwencj(cid:218) (szeregowo wykonywanych) instrukcji. Proces mo(cid:285)e zawiera(cid:202) dowoln(cid:200) liczb(cid:218) w(cid:200)tków. Pojawiaj(cid:200)ce si(cid:218) problemy wynikaj(cid:200) ze z(cid:239)o(cid:285)ono(cid:258)ci zwi(cid:200)zanej z synchronizacj(cid:200) w(cid:200)tków. Bardzo trudno modeluje si(cid:218) wysoce wspó(cid:239)bie(cid:285)ne rozwi(cid:200)zania za pomoc(cid:200) w(cid:200)tków, w szczególno(cid:258)ci w mo- delach, w których dochodzi do wspó(cid:239)dzielenia stanu. Nie(cid:239)atwo przewidzie(cid:202) wszystkie scenariusze oddzia(cid:239)ywania jednego w(cid:200)tku na drugi, je(cid:258)li nie wiadomo dok(cid:239)adnie, kiedy asynchronicznie wykonywany w(cid:200)tek zako(cid:241)czy swoje dzia(cid:239)ania. (cid:81) Wspó(cid:239)dzielona pami(cid:218)(cid:202) i zwi(cid:200)zane z tym blokowanie powoduj(cid:200), (cid:285)e bardzo trudno co(cid:258) wnioskowa(cid:202) o dzia(cid:239)aniu systemu, szczególnie gdy jest bardzo skomplikowany. 22 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Doceni(cid:252) Node (cid:81) Komunikacja mi(cid:218)dzy zadaniami wymaga implementacji du(cid:285)ej liczby elementów synchronizuj(cid:200)cych, takich jak blokady, semafory, zmienne warunkowe itp. Ju(cid:285) trudne (cid:258)rodowisko wymaga naprawd(cid:218) z(cid:239)o(cid:285)onych narz(cid:218)dzi, co zmusza do dysponowania spor(cid:200) wiedz(cid:200) nawet w przypadku tworzenia relatywnie prostego systemu. (cid:81) Wy(cid:258)cig i blokada wzajemna to typowe b(cid:239)(cid:218)dy pojawiaj(cid:200)ce si(cid:218) w tego rodzaju systemach. Ws\z odpowiedni(cid:200) kolejno(cid:258)ci(cid:200) operacji, bo dwa w(cid:200)tki mog(cid:200) uczestniczy(cid:202) w wy(cid:258)cigu o w(cid:239)a(cid:258)ciw(cid:200) zmian(cid:218) stanu, zdarzenia lub innej kluczowej charakterystyki systemu. (cid:81) Poniewa(cid:285) zachowanie odpowiednich granic mi(cid:218)dzy w(cid:200)tkami i ich stanami jest tak trudne, zapewnienie, (cid:285)e biblioteka (w przypadku Node b(cid:218)dzie to pakiet lub modu(cid:239)) jest bezpieczna w(cid:200)tkowo, wymaga po(cid:258)wi(cid:218)cenia mnóstwa czasu po stronie programisty. Czy wiem, (cid:285)e biblioteka nie zniszczy pewnej cz(cid:218)(cid:258)ci mojej aplikacji? Zagwarantowanie bezpiecze(cid:241)stwa w(cid:200)tkowego wymaga od twórcy biblioteki du(cid:285)ej uwagi, a gwarancje mog(cid:200) te(cid:285) by(cid:202) warunkowe — na przyk(cid:239)ad biblioteka mo(cid:285)e wskaza(cid:202), (cid:285)e jest bezpieczna w(cid:200)tkowo w kwestii odczytu, ale nie w kwestii zapisu. Chcieliby(cid:258)my uzyska(cid:202) szybko(cid:258)(cid:202) zwi(cid:200)zan(cid:200) ze zrównolegleniem dzi(cid:218)ki w(cid:200)tkom, ale bez zaprz(cid:200)tania sobie g(cid:239)owy semaforami i blokadami. W (cid:258)wiecie systemu Unix ten pomys(cid:239) nazywa si(cid:218) cz(cid:218)sto regu(cid:239)(cid:200) prostoty: programi(cid:258)ci powinni w trakcie projektowania d(cid:200)(cid:285)y(cid:202) do prostoty i poszukiwa(cid:202) sposobów podzia(cid:239)u programu na niewielkie, wspó(cid:239)pracuj(cid:200)ce ze sob(cid:200) elementy; zniech(cid:218)ca si(cid:218) tak programistów do tworzenia wspaniale z(cid:239)o(cid:285)onych systemów, które w praktyce s(cid:200) programami nara- (cid:285)onymi na b(cid:239)(cid:218)dy. Wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) i procesy Zrównoleglenie w jednym procesie to z(cid:239)o(cid:285)ona iluzja osi(cid:200)gana dzi(cid:218)ki bardzo wyrafinowanemu sprz(cid:218)towi i oprogramowaniu. Tak naprawd(cid:218) jednak ka(cid:285)demu zale(cid:285)y na postrzeganym dzia(cid:239)aniu — jak system dzia(cid:239)a i jak jest programowany przez programist(cid:218). W(cid:200)tki powoduj(cid:200), (cid:285)e zrównolegle- nie jest bardzo wydajne, ale czyni(cid:200) wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) znacznie trudniejsz(cid:200) w analizie. Zamiast zrzuca(cid:202) z(cid:239)o(cid:285)ono(cid:258)(cid:202) tego rodzaju na programist(cid:218), Node sam zarz(cid:200)dza w(cid:200)tkami wej(cid:258)cia- wyj(cid:258)cia, upraszczaj(cid:200)c wszystko i wymagaj(cid:200)c od twórcy kodu jedynie sterowania przep(cid:239)ywem mi(cid:218)dzy poszczególnymi zdarzeniami. Istnieje potrzeba mikrozarz(cid:200)dzania w(cid:200)tkami wej(cid:258)cia- wyj(cid:258)cia — dzi(cid:218)ki temu programista projektuj(cid:200)cy aplikacj(cid:218) skupia si(cid:218) jedynie na miejscach dost(cid:218)pu do danych (wywo(cid:239)ania zwrotne) i instrukcjach wykonywanych, gdy dane b(cid:218)d(cid:200) ju(cid:285) dost(cid:218)pne. Pojedynczy strumie(cid:241) instrukcji, który jawnie przejmuje kontrol(cid:218) i si(cid:218) jej zrzeka, nie nara(cid:285)a nas na kolizje i jest przewidywalny. (cid:81) Zamiast martwi(cid:202) si(cid:218) o blokady i kolizje, programista skupia si(cid:218) na tworzeniu (cid:239)a(cid:241)cuchów instrukcji, których kolejno(cid:258)(cid:202) jest przewidywalna. (cid:81) Zrównoleglenie osi(cid:200)ga si(cid:218) za pomoc(cid:200) wielu procesów, gdzie ka(cid:285)dy proces posiada w(cid:239)asny obszar pami(cid:218)ci, co zapewnia nieskomplikowan(cid:200) komunikacj(cid:218) mi(cid:218)dzy procesami — dzi(cid:218)ki regule prostoty uzyskujemy nie tylko proste i prawdopodobnie bezb(cid:239)(cid:218)dne komponenty, ale równie(cid:285) poprawiamy interoperacyjno(cid:258)(cid:202). 23 Poleć książkęKup książkę Node.js. Projektowanie, wdra(cid:298)anie i utrzymywanie aplikacji (cid:81) Stan nie jest (dowolnie) wspó(cid:239)dzielony mi(cid:218)dzy poszczególnymi procesami Node. Proces automatycznie chroni si(cid:218) przed niespodziewanymi wizytami innych procesów, które mog(cid:239)yby zaj(cid:200)(cid:202) jego zasoby i namiesza(cid:202) w pami(cid:218)ci. Komunikacja odbywa si(cid:218) prostymi kana(cid:239)ami z u(cid:285)yciem prostych protoko(cid:239)ów, co znacz(cid:200)co utrudnia pisanie programów wykonuj(cid:200)cych nieprzewidywalne zmiany w innych procesach. (cid:81) Bezpiecze(cid:241)stwo w(cid:200)tkowe to co(cid:258), co przestaje by(cid:202) dla programisty jedn(cid:200) z trosk i przyczyn(cid:200) straty czasu. Poniewa(cid:285) wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) jednow(cid:200)tkowa zapobiega kolizjom trapi(cid:200)cym wspó(cid:239)bie(cid:285)no(cid:258)(cid:202) wielow(cid:200)tkow(cid:200), programowanie przebiega sprawniej i pewniej. Pojedynczy w(cid:200)tek opisuj(cid:200)cy asynchroniczne sterowanie przep(cid:239)ywem i zarz(cid:200)dzany efektywnie przez p(cid:218)tl(cid:218) zdarze(cid:241) zapewnia stabilno(cid:258)(cid:202), czytelno(cid:258)(cid:202), (cid:239)atwo(cid:258)(cid:202) konserwacji i du(cid:285)(cid:200) odporno(cid:258)(cid:202) na b(cid:239)(cid:218)dy programów Node. Dobr(cid:200) wiadomo(cid:258)ci(cid:200) jest to, (cid:285)e Node w du(cid:285)ej mierze pozwala wykorzy- sta(cid:202) szybko(cid:258)(cid:202) i si(cid:239)(cid:218) wielow(cid:200)tkowo(cid:258)ci — dzi(cid:218)ki sprytnemu zaprojektowaniu si(cid:239)a ta jest transpa- rentna dla programisty, wi(cid:218)c potrafi on z niej skorzysta(cid:202) przy du(cid:285)o mniejszym wysi(cid:239)ku. Zdarzenia Wiele rozszerze(cid:241) JavaScript dost(cid:218)pnych w Node emituje zdarzenia. S(cid:200) to instancje events. (cid:180)EventEmitter. Ka(cid:285)dy obiekt mo(cid:285)e rozszerza(cid:202) EventEmitter, co pozwala programistom budowa(cid:202) zwi(cid:218)z(cid:239)e, asynchroniczne interfejsy dla metod obiektowych. Przyjrzymy si(cid:218) teraz prostemu przyk(cid:239)adowi, który ilustruje wykorzystanie obiektu EventEmitter jako prototypu dla konstruktora. Poniewa(cid:285) ka(cid:285)da tworzona w ten sposób instancja b(cid:218)dzie posia- da(cid:239)a obiekt EventEmitter w (cid:239)a(cid:241)cuchu prototypów, this zapewni naturalny dost(cid:218)p do API (ang. Application Programming Interface) zdarze(cid:241). Metody instancji mog(cid:200) emitowa(cid:202) zdarzenia, a te mo- g(cid:200) by(cid:202) nas(cid:239)uchiwane. W przyk(cid:239)adzie emitujemy zdarzenie z najnowsz(cid:200) warto(cid:258)ci(cid:200) licznika po wywo(cid:239)aniu metody counter.increment. W innym fragmencie kodu nas(cid:239)uchujemy zdarzenia incremented i po prostu wy(cid:258)wietlamy zawarto(cid:258)(cid:202) licznika w wierszu polece(cid:241). var EventEmitter = require( events ).EventEmitter; var util = require( util ); var Counter = function(init) { this.increment = function() { init++; this.emit( incremented , init); } } util.inherits(Counter, EventEmitter); var counter = new Counter(10); var callback = function(count) { console.log(count); 24 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Doceni(cid:252) Node } counter.addListener( incremented , callback); counter.increment(); // 11 counter.increment(); // 12 Dost(cid:218)p do przyk(cid:239)adów Wszystkie prezentowane w ksi(cid:200)(cid:285)ce przyk(cid:239)ady znajdziesz w pliku dost(cid:218)pnym na stronie wydawnictwa pod adresem ftp://ftp.helion.pl/przyklady/nodepr.zip. Aby usun(cid:200)(cid:202) funkcj(cid:218) nas(cid:239)uchuj(cid:200)c(cid:200) zdarzenia przypisan(cid:200) do counter, u(cid:285)yj polecenia counter. (cid:180)removeListener( incremented , callback). Obiekt EventEmitter jest rozszerzalny, wi(cid:218)c mo(cid:285)na skorzysta(cid:202) z pe(cid:239)nej elastyczno(cid:258)ci j(cid:218)zyka JavaScript. Na przyk(cid:239)ad obs(cid:239)ug(cid:218) strumieni danych wej(cid:258)cia-wyj(cid:258)cia mo(cid:285)na obs(cid:239)u(cid:285)y(cid:202) w sposób ba- zuj(cid:200)cy na zdarzeniach przy zachowaniu zasady asynchronicznego, nieblokuj(cid:200)cego programowa- nia obowi(cid:200)zuj(cid:200)cej w Node: var stream = require( stream ); var Readable = stream.Readable; var util = require( util ); var Reader = function() { Readable.call(this); this.counter = 0; } util.inherits(Reader, Readable); Reader.prototype._read = function() { if(++this.counter 10) { return this.push(null); } this.push(this.counter.toString()); }; // Po zaj(cid:286)ciu zdarzenia #data wy(cid:286)wietl fragment danych. var reader = new Reader(); reader.setEncoding( utf8 ); reader.on( data , function(chunk) { console.log(chunk); }); reader.on( end , function() { console.log( --zako(cid:241)czono-- ); }); W przedstawionym programie u(cid:285)ywamy strumienia Reader wysy(cid:239)aj(cid:200)cego zbiór liczb — element nas(cid:239)uchuj(cid:200)cy zdarzenia data strumienia pobiera liczby, gdy s(cid:200) generowane, i wy(cid:258)wietla je na 25 Poleć książkęKup książkę Node.js. Projektowanie, wdra(cid:298)anie i utrzymywanie aplikacji ekranie. Po zako(cid:241)czeniu strumienia program wy(cid:258)wietla dodatkowy komunikat o ko(cid:241)cu strumie- nia. Kod nas(cid:239)uchuj(cid:200)cy jest wywo(cid:239)ywany raz na ka(cid:285)d(cid:200) liczb(cid:218), co oznacza, (cid:285)e wykonywanie zbioru liczb nie blokuje p(cid:218)tli zdarze(cid:241). Poniewa(cid:285) p(cid:218)tla zdarze(cid:241) Node musi zapewni(cid:202) zasoby tylko do obs(cid:239)ugi wywo(cid:239)a(cid:241) zwrotnych, wiele innych instrukcji mo(cid:285)e zosta(cid:202) wykonanych mi(cid:218)dzy ka(cid:285)- dym zdarzeniem. P(cid:218)tla zdarze(cid:241) Kod stosowany w oprogramowaniu, które nie korzysta z sieci, jest najcz(cid:218)(cid:258)ciej synchroniczny i blokuj(cid:200)cy. Operacje wej(cid:258)cia-wyj(cid:258)cia w poni(cid:285)szym pseudokodzie równie(cid:285) s(cid:200) blokuj(cid:200)ce: variable = produceAValue() print variable // Pewna warto(cid:286)(cid:252) zostanie wy(cid:286)wietlona po zako(cid:276)czeniu #produceAValue. Poni(cid:285)sza iteracja b(cid:218)dzie odczytywa(cid:239)a zawarto(cid:258)(cid:202) jednego pliku, wy(cid:258)wietla(cid:239)a j(cid:200), a nast(cid:218)pnie prze- chodzi(cid:239)a do nast(cid:218)pnego pliku a(cid:285) do zako(cid:241)czenia p(cid:218)tli: fileNames = [ a , b , c ] while(filename = fileNames.shift()) { fileContents = File.read(filename) print fileContents } // a // b // c To dobre rozwi(cid:200)zanie w wielu sytuacjach. Ale co si(cid:218) stanie, je(cid:258)li pliki s(cid:200) bardzo du(cid:285)e? Je(cid:258)li pobra- nie jednego pliku zajmie sekund(cid:218), pobranie wszystkich zajmie trzy sekundy. Pobieranie jednego pliku czeka na pobranie wcze(cid:258)niejszego, co jest ma(cid:239)o wydajne i powolne. Wykorzystuj(cid:200)c Node, mo(cid:285)emy zainicjowa(cid:202) jednoczesny odczyt wszystkich trzech plików: var fs = require( fs ); var fileNames = [ a , b , c ]; fileNames.forEach(function(filename) { fs.readFile(filename, {encoding: utf8 }, function(err, content) { console.log(content); }); }); // b // a // c Ta wersja odczyta wszystkie trzy pliki jednocze(cid:258)nie. Ka(cid:285)de wywo(cid:239)anie fs.readFile zwróci wynik w pewnym nieznanym momencie w przysz(cid:239)o(cid:258)ci. Nie mo(cid:285)emy w tej sytuacji mie(cid:202) pewno(cid:258)ci, (cid:285)e pliki wy(cid:258)wietl(cid:200) si(cid:218) w zadanej kolejno(cid:258)ci. W wielu sytuacjach czas niezb(cid:218)dny na pobranie wszystkich trzech plików b(cid:218)dzie podobny do czasu potrzebnego na pobranie jednego z nich, czyli b(cid:218)dzie zdecydowanie krótszy ni(cid:285) trzy sekundy. Zamienili(cid:258)my przewidywaln(cid:200) kolejno(cid:258)(cid:202) wy(cid:258)wietlenia na szybko(cid:258)(cid:202) dzia(cid:239)ania i podobnie jak dla w(cid:200)tków synchronizacja wspó(cid:239)bie(cid:285)nego 26 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Doceni(cid:252) Node (cid:258)rodowiska wymaga pewnej dodatkowej pracy. W jaki sposób zarz(cid:200)dza(cid:202) nieprzewidywalnymi zdarzeniami i jak je opisywa(cid:202), aby kod by(cid:239) przejrzysty oraz wydajny? Kluczow(cid:200) decyzj(cid:200) projektow(cid:200) dokonan(cid:200) przez twórców Node by(cid:239)o zaimplementowanie p(cid:218)- tli zdarze(cid:241) jako mened(cid:285)era wspó(cid:239)bie(cid:285)no(cid:258)ci. Poni(cid:285)szy opis programowania bazuj(cid:200)cego na zdarze- niach (to fragment ze strony http://www.princeton.edu/~achaney/tmve/wiki100k/docs/Event-driven_ programming.html) nie tylko opisuje paradygmat sterowania zdarzeniami, ale równie(cid:285) wpro- wadza w mechanizm dzia(cid:239)ania zdarze(cid:241) w Node i wyja(cid:258)nia, dlaczego JavaScript jest idealnym j(cid:218)zykiem dla tego rodzaju paradygmatu. W programowaniu komputerowym programowanie wykorzystuj(cid:200)ce zdarzenia lub pro- gramowanie bazuj(cid:200)ce na zdarzeniach to paradygmat, w którym przebiegiem programu steruj(cid:200) zdarzenia — wyj(cid:258)cie sensora, akcja u(cid:285)ytkownika (klikni(cid:218)cie, naci(cid:258)ni(cid:218)cie klawisza) lub komunikat z innego programu lub w(cid:200)tku. Programowanie wykorzystuj(cid:200)ce zdarzenia mo(cid:285)na równie(cid:285) zdefiniowa(cid:202) jako sposób tworze- nia architektury aplikacji, w której aplikacja posiada g(cid:239)ówn(cid:200) p(cid:218)tl(cid:218) podzielon(cid:200) na dwie cz(cid:218)(cid:258)ci: pierwsz(cid:200) jest wybór zdarzenia (lub wykrywanie zdarze(cid:241)), a drug(cid:200) jest obs(cid:239)uga zdarzenia (…). Programy sterowane zdarzeniami mo(cid:285)na tworzy(cid:202) w dowolnym j(cid:218)zyku programowania, ale zadanie to jest (cid:239)atwiejsze, je(cid:258)li ma si(cid:218) do dyspozycji abstrakcje wysokiego poziomu, na przyk(cid:239)ad domkni(cid:218)cia. Jak wcze(cid:258)niej wykazali(cid:258)my, (cid:258)rodowiska jednow(cid:200)tkowe b(cid:218)d(cid:200) si(cid:218) blokowa(cid:239)y, a co za tym idzie, b(cid:218)d(cid:200) dzia(cid:239)a(cid:239)y powoli. V8 to jednow(cid:200)tkowe (cid:258)rodowisko wykonawcze dla programów JavaScript. W jaki sposób t(cid:218) architektur(cid:218) jednow(cid:200)tkow(cid:200) uczyni(cid:202) efektywn(cid:200)? Node czyni pojedyncze w(cid:200)tki wydajniejszymi, bo deleguje wiele operacji blokuj(cid:200)cych do ele- mentów systemu operacyjnego, wi(cid:218)c g(cid:239)ówny w(cid:200)tek V8 dzia(cid:239)a tylko wtedy, gdy s(cid:200) dane do obróbki. G(cid:239)ówny w(cid:200)tek (program wykonywany przez Node) wyra(cid:285)a zainteresowanie pewnymi danymi (na przyk(cid:239)ad poprzez fs.readFile) i przekazuje wywo(cid:239)anie zwrotne pozwalaj(cid:200)ce na otrzymanie informacji, gdy dane b(cid:218)d(cid:200) dost(cid:218)pne. Dopóki dane nie nadejd(cid:200), g(cid:239)ówny w(cid:200)tek V8 mo(cid:285)e realizo- wa(cid:202) inne zadania. Jak to si(cid:218) dzieje? Node deleguje zadania wej(cid:258)cia-wyj(cid:258)cia do biblioteki libuv, któr(cid:200) mo(cid:285)na opisa(cid:202) nast(cid:218)puj(cid:200)co (to fragment ze strony http://nikhilm.github.io/uvbook/basics. (cid:180)html#event-loops): W programowaniu wykorzystuj(cid:200)cym zdarzenia aplikacja wyra(cid:285)a zainteresowanie pewnymi zdarzeniami i reaguje na nie, gdy ju(cid:285) zajd(cid:200). Odpowiedzialno(cid:258)(cid:202) za zbieranie zdarze(cid:241) z sys- temu operacyjnego i monitorowanie innych (cid:283)róde(cid:239) zdarze(cid:241) to zadanie biblioteki libuv. U(cid:285)ytkownik biblioteki jedynie rejestruje funkcje zwrotne wywo(cid:239)ywane w momencie zaj(cid:258)cia zdarzenia. W przedstawionym cytacie u(cid:285)ytkownik to proces Node wykonuj(cid:200)cy program JavaScript. Wywo- (cid:239)ania zwrotne to funkcje JavaScript. Za zarz(cid:200)dzanie wywo(cid:239)aniami zwrotnymi odpowiada p(cid:218)tla zdarze(cid:241) Node. Node zarz(cid:200)dza kolejk(cid:200) (cid:285)(cid:200)da(cid:241) wej(cid:258)cia-wyj(cid:258)cia, stosuj(cid:200)c libuv, które odpowiada 27 Poleć książkęKup książkę Node.js. Projektowanie, wdra(cid:298)anie i utrzymywanie aplikacji za komunikacj(cid:218) z systemem operacyjnym i przekazanie wyniku do funkcji zwrotnej napisanej w j(cid:218)zyku JavaScript. Rozwa(cid:285)my nast(cid:218)puj(cid:200)cy kod: var fs = require( fs ); fs.readFile( test.js , {encoding: utf8 }, function(err, fileContents) { console.log( Nast(cid:218)pnie jest dost(cid:218)pna tre(cid:258)(cid:202): , fileContents); }); console.log( To nast(cid:200)pi wcze(cid:258)niej. ); Program wy(cid:258)wietli poni(cid:285)szy wynik: To nast(cid:200)pi wcze(cid:258)niej. Nast(cid:218)pnie jest dost(cid:218)pna tre(cid:258)(cid:202): [tre(cid:258)(cid:202) pliku] Oto co si(cid:218) dzieje w Node w trakcie wykonywania programu. (cid:81) Node wczytuje modu(cid:239) fs. Zapewnia on dost(cid:218)p do fs.binding, które jest „odwzorowaniem statycznym zdefiniowanym w src/node.cc, które (cid:239)(cid:200)czy kod C++ i JavaScript” (https://groups.google.com/forum/#!msg/nodejs/R5fDzBr0eEk/lrCKaJX_6vIJ). (cid:81) Metoda fs.readFile otrzymuje instrukcje dotycz(cid:200)ce pliku i wywo(cid:239)anie zwrotne w postaci funkcji JavaScript. Poprzez fs.binding libuv zostaje powiadomione o (cid:285)(cid:200)daniu odczytu pliku i otrzymuje specjalnie przygotowan(cid:200) wersj(cid:218) wywo(cid:239)ania zwrotnego, zapewniaj(cid:200)c(cid:200) pó(cid:283)niejsze uruchomienie w(cid:239)a(cid:258)ciwej funkcji. (cid:81) Biblioteka libuv wywo(cid:239)uje funkcje systemu operacyjnego niezb(cid:218)dne do odczytu pliku, wykorzystuj(cid:200)c przy tym w(cid:239)asn(cid:200) pul(cid:218) w(cid:200)tków. (cid:81) Program JavaScript kontynuuje dzia(cid:239)anie, wy(cid:258)wietlaj(cid:200)c To nast(cid:200)pi wcze(cid:258)niej. Poniewa(cid:285) jest aktywne wywo(cid:239)anie zwrotne, p(cid:218)tla zdarze(cid:241) czeka na otrzymanie informacji zwrotnej. (cid:81) Gdy deskryptor pliku zostanie odczytany przez system operacyjny, libuv (poprzez wewn(cid:218)trzne mechanizmy) jest o tym informowane i zostaje uruchomione wywo(cid:239)anie zwrotne przekazane do libuv, które w praktyce przygotowuje oryginalne wywo(cid:239)anie zwrotne do umieszczenia w g(cid:239)ównym w(cid:200)tku (wykonywanym przez V8). (cid:81) Oryginalne wywo(cid:239)anie zwrotne trafia do kolejki p(cid:218)tli zdarze(cid:241) i b(cid:218)dzie wykonane w nast(cid:218)pnym cyklu. (cid:81) Zawarto(cid:258)(cid:202) pliku zostaje wy(cid:258)wietlona na ekranie. (cid:81) Poniewa(cid:285) nie ma innych wywo(cid:239)a(cid:241) zwrotnych, proces ko(cid:241)czy swoje dzia(cid:239)anie. Tutaj widzimy kluczowe rozwi(cid:200)zania, które Node stosuje do obs(cid:239)ugi szybkiego, (cid:239)atwego w zarz(cid:200)- dzaniu i skalowalnego wej(cid:258)cia-wyj(cid:258)cia. Je(cid:258)li program 10 razy odczytywa(cid:239)by plik test.js, (cid:239)(cid:200)czny czas realizacji pozosta(cid:239)by mniej wi(cid:218)cej taki sam. Ka(cid:285)de wywo(cid:239)anie by(cid:239)oby uruchomione równole- gle w swoim w(cid:239)asnym w(cid:200)tku w puli w(cid:200)tków biblioteki libuv. Cho(cid:202) pisali(cid:258)my kod w JavaScript, tak naprawd(cid:218) uruchomili(cid:258)my bardzo wydajn(cid:200), wielow(cid:200)tkow(cid:200) maszyneri(cid:218), ale unikn(cid:218)li(cid:258)my bólu g(cid:239)owy zwi(cid:200)zanego z zarz(cid:200)dzaniem w(cid:200)tkami. Przyjrzyjmy si(cid:218) bli(cid:285)ej, w jaki sposób wyniki biblioteki libuv trafiaj(cid:200) do g(cid:239)ównej p(cid:218)tli zdarze(cid:241). 28 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Doceni(cid:252) Node Gdy dane staj(cid:200) si(cid:218) dost(cid:218)pne na poziomie interfejsu gniazda sieciowego lub strumienia, nie mo(cid:285)e- my od razu wykona(cid:202) funkcji wywo(cid:239)ania zwrotnego. JavaScript jest jednow(cid:200)tkowy, wi(cid:218)c wyniki trzeba synchronizowa(cid:202). Nie mo(cid:285)emy nagle zmieni(cid:202) stanu w (cid:258)rodku cyklu p(cid:218)tli zdarze(cid:241) — dopro- wadzi(cid:239)oby to do klasycznych problemów trapi(cid:200)cych aplikacje wielow(cid:200)tkowe, takich jak wy(cid:258)cig, konflikty w dost(cid:218)pie do pami(cid:218)ci itp. Przy wej(cid:258)ciu do p(cid:218)tli zdarze(cid:241) Node wykonuje (w praktyce) kopi(cid:218) aktualnej kolejki instrukcji (na- zywanej stosem), czy(cid:258)ci oryginaln(cid:200) kolejk(cid:218) i uruchamia jej kopi(cid:218). Przetwarzanie tej kolejki instrukcji nazywa si(cid:218) cyklem. Je(cid:258)li libuv otrzyma wyniki asynchronicznie, gdy zbiór instrukcji skopiowany na pocz(cid:200)tku cyklu jest w trakcie realizacji przez g(cid:239)ówny w(cid:200)tek (V8), wynik (otoczony wywo(cid:239)aniem zwrotnym) jest kolejkowany. Gdy aktualna kolejka zostanie wyczyszczona i zako(cid:241)czy si(cid:218) jej ostatnia instrukcja, kolejka b(cid:218)dzie sprawdzana pod k(cid:200)tem instrukcji do wykonania w na- st(cid:218)pnym cyklu. Wzorzec sprawdzania i wykonywania kolejki b(cid:218)dzie si(cid:218) powtarza(cid:239) (w p(cid:218)tli) a(cid:285) do wyczyszczenia kolejki zada(cid:241). W takiej sytuacji nie b(cid:218)d(cid:200) ju(cid:285) przyjmowane (cid:285)adne dodatkowe dane i proces Node po prostu si(cid:218) zako(cid:241)czy. Dost(cid:218)pna pod adresem https://github.com/nodejs/node-v0.x-archive/issues/5798 dyskusja mi(cid:218)dzy g(cid:239)ównymi programistami Node na temat implementacji process.nextTick i setImmediate zawiera wiele bardzo dok(cid:239)adnych informacji na temat dzia(cid:239)ania p(cid:218)tli zdarze(cid:241). Oto lista rodzajów zdarze(cid:241) wej(cid:258)cia-wyj(cid:258)cia, które trafiaj(cid:200) do kolejki. (cid:81) Bloki wykonawcze — to bloki kodu JavaScript zawieraj(cid:200)ce w(cid:239)a(cid:258)ciwy program Node; s(cid:200) to funkcje, wyra(cid:285)enia, p(cid:218)tle itp. Dotyczy to równie(cid:285) zdarze(cid:241) EventEmitter zg(cid:239)oszonych w aktualnym kontek(cid:258)cie wykonywania. (cid:81) Opó(cid:283)nienia czasowe — to funkcje wywo(cid:239)ania zwrotnego wskazane do wykonania w przysz(cid:239)o(cid:258)ci po czasie okre(cid:258)lonym w milisekundach za pomoc(cid:200) funkcji takich jak setTimeout i setInterval. (cid:81) Wej(cid:258)cie-wyj(cid:258)cie — przygotowane wywo(cid:239)ania zwrotne zwracane do g(cid:239)ównego w(cid:200)tku po ich wcze(cid:258)niejszym oddelegowaniu do puli w(cid:200)tków zarz(cid:200)dzanych przez Node. Dotycz(cid:200) one obs(cid:239)ugi plików i ruchu sieciowego. (cid:81) Opó(cid:283)nione bloki wykonawcze — to najcz(cid:218)(cid:258)ciej funkcje umieszczone na stosie zgodnie z zasadami wyznaczonymi przez funkcje setImmediate i process.nextTick. Warto pami(cid:218)ta(cid:202) o dwóch wa(cid:285)nych kwestiach. (cid:81) Nie uruchamia si(cid:218) i nie zatrzymuje p(cid:218)tli zdarze(cid:241). P(cid:218)tla zaczyna dzia(cid:239)a(cid:202) w momencie uruchomienia procesu i ko(cid:241)czy si(cid:218), gdy nie ma ju(cid:285) (cid:285)adnych wywo(cid:239)a(cid:241) zwrotnych do obs(cid:239)u(cid:285)enia. Oznacza to, (cid:285)e p(cid:218)tla mo(cid:285)e dzia(cid:239)a(cid:202) wiecznie. (cid:81) P(cid:218)tla zdarze(cid:241) wykonuje si(cid:218) w jednym w(cid:200)tku, ale operacje wej(cid:258)cia-wyj(cid:258)cia deleguje do biblioteki libuv, która zarz(cid:200)dza pul(cid:200) w(cid:200)tków, wykonuje dzia(cid:239)ania równolegle i powiadamia p(cid:218)tl(cid:218) zdarze(cid:241) o ich zrealizowaniu lub otrzymaniu cz(cid:218)(cid:258)ci wyników. Uzyskuje si(cid:218) w ten sposób bezpiecze(cid:241)stwo programowania jednow(cid:200)tkowego przy jednoczesnym wykorzystaniu wielu zalet systemu wielow(cid:200)tkowego. 29 Poleć książkęKup książkę Node.js. Projektowanie, wdra(cid:298)anie i utrzymywanie aplikacji Aby dowiedzie(cid:202) si(cid:218) wi(cid:218)cej na temat tego, w jaki sposób Node korzysta z biblioteki libuv i innych g(cid:239)ównych bibliotek, przejrzyj kod modu(cid:239)u fs dost(cid:218)pny pod adresem https://github.com/nodejs/ node/blob/master/lib/fs.js. Porównaj metody fs.read i fs.readSync, aby pozna(cid:202) ró(cid:285)nic(cid:218) w obs(cid:239)udze wersji synchronicznej i asynchronicznej. Zwró(cid:202) te(cid:285) uwag(cid:218) na wywo(cid:239)anie zwrotne wrapper przeka- zywane do metody binding.read w metodzie fs.read. Aby jeszcze dok(cid:239)adniej przyjrze(cid:202) si(cid:218), jak zosta(cid:239) zaprojektowany Node, w(cid:239)(cid:200)czaj(cid:200)c w to implementa- cj(cid:218) kolejki, przejrzyj jego kod (cid:283)ród(cid:239)owy dost(cid:218)pny pod adresem https://github.com/nodejs/ node/tree/master/src. Prze(cid:258)led(cid:283) MakeCallback w plikach fs_event_wrap.cc i node.cc. Sprawd(cid:283) te(cid:285) klas(cid:218) req_wrap, otoczk(cid:218) dla silnika JavaScript V8, która znajduje si(cid:218) w pliku node_file.cc, a jej definicja w pliku req_wrap.h. Wp(cid:239)yw sposobu zaprojektowania Node na architektów systemów Node to nadal stosunkowo nowa technologia. Przekroczy(cid:239)a wersj(cid:218) 1.0 ju(cid:285) jaki(cid:258) czas temu i ca(cid:239)y czas si(cid:218) rozwija. B(cid:239)(cid:218)dy bezpiecze(cid:241)stwa s(cid:200) znajdowane i poprawiane. Wycieki pami(cid:218)ci s(cid:200) znajdo- wane i naprawiane. Eran Hammer, o którym wspomnia(cid:239)em na pocz(cid:200)tku rozdzia(cid:239)u, a tak(cid:285)e ca(cid:239)y jego zespó(cid:239) w Walmart Labs, aktywnie uczestnicz(cid:200) w rozwoju Node, szczególnie je(cid:258)li znajd(cid:200) b(cid:239)(cid:218)dy! Dotyczy to równie(cid:285) wielu innych du(cid:285)ych firm, które wykorzystuj(cid:200) Node, np. firmy PayPal. Je(cid:258)li wybra(cid:239)e(cid:258) Node, a Twoja aplikacja osi(cid:200)gn(cid:218)(cid:239)a rozmiar, który powoduje ch(cid:218)(cid:202) si(cid:218)gni(cid:218)cia po ksi(cid:200)(cid:285)- k(cid:218) na temat wdra(cid:285)ania Node, masz mo(cid:285)liwo(cid:258)(cid:202) nie tylko skorzystania z wiedzy spo(cid:239)eczno(cid:258)ci, ale równie(cid:285) samodzielnego stworzenia odpowiedniego (cid:258)rodowiska. Node to projekt otwartego oprogramowania, wi(cid:218)c mo(cid:285)esz zg(cid:239)asza(cid:202) w(cid:239)asne poprawki i udoskonalenia. Poza zdarzeniami istniej(cid:200) jeszcze dwa inne kluczowe elementy, których zrozumienie niezb(cid:218)dne jest do opanowania Node na nieco g(cid:239)(cid:218)bszym poziomie — budowanie systemów z mniejszych cz(cid:218)- (cid:258)ci i wykorzystanie zdarzeniowych wersji strumieni wraz z przekazywaniem mi(cid:218)dzy nimi danych. Budowanie wi(cid:218)kszych systemów z mniejszych W swojej ksi(cid:200)(cid:285)ce UNIX. Sztuka programowania Eric Raymond zaproponowa(cid:239) regu(cid:239)(cid:218) modularno(cid:258)ci: Jedynym sposobem pisania skomplikowanego oprogramowania, które nie b(cid:218)dzie si(cid:218) spekta- kularnie wyk(cid:239)ada(cid:202), jest ograniczenie jego ogólnej z(cid:239)o(cid:285)ono(cid:258)ci — budowanie programów z prostych cz(cid:218)(cid:258)ci po(cid:239)(cid:200)czonych dobrze zdefiniowanymi interfejsami, aby wi(cid:218)kszo(cid:258)(cid:202) proble- mów mia(cid:239)a charakter lokalny i by(cid:239)a nadzieja na to, (cid:285)e uda si(cid:218) ulepszy(cid:202) jedn(cid:200) z cz(cid:218)(cid:258)ci bez psucia ca(cid:239)o(cid:258)ci. 30 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Doceni(cid:252) Node Pomys(cid:239) budowania z(cid:239)o(cid:285)onych systemów z „prostych, lu(cid:283)no po(cid:239)(cid:200)czonych cz(cid:218)(cid:258)ci” napotyka si(cid:218) w teorii zarz(cid:200)dzania, teorii rz(cid:200)dzenia, przemy(cid:258)le i wielu innych kontekstach. W aspekcie tworze- nia oprogramowania zaleca si(cid:218) programistom tworzenie i stosowanie jedynie najprostszych, najbardziej u(cid:285)ytecznych komponentów niezb(cid:218)dnych do poprawnego dzia(cid:239)ania w wi(cid:218)kszym systemie. Du(cid:285)e systemy znacznie trudniej analizowa(cid:202), szczególnie je(cid:258)li granice poszczególnych komponentów nie s(cid:200) dobrze zarysowane. Jedn(cid:200) z podstawowych trudno(cid:258)ci w trakcie konstruowania skalowalnych programów JavaScript jest brak standardowego interfejsu do sk(cid:239)adania wi(cid:218)kszego programu z mniejszych cz(cid:218)(cid:258)ci. Na przyk(cid:239)ad typowa aplikacja internetowa mo(cid:285)e wczytywa(cid:202) zale(cid:285)no(cid:258)ci za pomoc(cid:200) zestawu znaczni- ków script w sekcji head dokumentu HTML (ang. HyperText Markup Language): head script src= plikA.js /script script src= plikB.js /script /head Tego rodzaju system ma wiele wad. (cid:81) Wszystkie potencjalne zale(cid:285)no(cid:258)ci trzeba wcze(cid:258)niej zadeklarowa(cid:202) — dynamiczne dodawanie zale(cid:285)no(cid:258)ci wymaga dodatkowych sztuczek. (cid:81) Poszczególne skrypty nie s(cid:200) odpowiednio zahermetyzowane — nic nie zablokuje sytuacji, w której kilka plików zmieni jaki(cid:258) globalny obiekt. Przestrzenie nazw mog(cid:200) (cid:239)atwo ze sob(cid:200) kolidowa(cid:202), co czyni dowolne wstrzykiwanie kodu dosy(cid:202) niebezpiecznym. (cid:81) Plik plikA.js nie mo(cid:285)e skorzysta(cid:202) z plikB.js jako kolekcji, czyli na przyk(cid:239)ad u(cid:285)y(cid:202) zapisu kontekstowego typu plikB.metoda. (cid:81) Rozwi(cid:200)zanie ze znacznikiem script powsta(cid:239)o, zanim zacz(cid:218)to tak naprawd(cid:218) projektowa(cid:202) systemy modu(cid:239)owe, wi(cid:218)c nie wie nic o zale(cid:285)no(cid:258)ciach i wersjonowaniu. (cid:81) Skryptów nie mo(cid:285)na (cid:239)atwo usun(cid:200)(cid:202) lub nadpisa(cid:202). (cid:81) Z powodu wszystkich wymienionych zagro(cid:285)e(cid:241) wspó(cid:239)dzielenie nie jest tak (cid:239)atwe, jak mog(cid:239)oby by(cid:202), co utrudnia wspó(cid:239)prac(cid:218) w otwartym ekosystemie. Ambiwalentne wstawianie w aplikacji nieprzewidywalnych fragmentów kodu przeczy ch(cid:218)ci za- pewniania przewidywalnej funkcjonalno(cid:258)ci. Tak naprawd(cid:218) potrzebny jest pewien standard wczy- tywania i wspó(cid:239)dzielenia niezale(cid:285)nych modu(cid:239)ów programu. W odpowiedzi na to wyzwanie Node wprowadzi(cid:239)o poj(cid:218)cie pakietu, który bazuje na specyfikacji CommonJS. Pakiet to zbiór plików z kodem po(cid:239)(cid:200)czonych w jedn(cid:200) ca(cid:239)o(cid:258)(cid:202) za pomoc(cid:200) pliku manife- stu opisuj(cid:200)cego ca(cid:239)y zbiór. Zale(cid:285)no(cid:258)ci, autorstwo, cel, struktura i inne istotne dane znajduj(cid:200) si(cid:218) w pliku manifestu w ustandaryzowanym formacie. Zach(cid:218)ca to do tworzenia du(cid:285)ych systemów z wielu ma(cid:239)ych, niezale(cid:285)nych podsystemów. Co wa(cid:285)niejsze, zach(cid:218)ca do wspó(cid:239)dzielenia si(cid:218) kodem. To, co tu opisuj(cid:218), nie jest problemem technicznym. To kwestia zbierania si(cid:218) ludzi razem i podejmowania decyzji, które inicjuj(cid:200) post(cid:218)p i wspólne budowanie czego(cid:258) wi(cid:218)kszego i lepszego. — Kevin Dangoor, twórca CommonJS 31 Poleć książkęKup książkę Node.js. Projektowanie, wdra(cid:298)anie i utrzymywanie aplikacji W du(cid:285)ej mierze sukces Node wynika z ogromnej liczby i nierzadko wysokiej jako(cid:258)ci pakietów udost(cid:218)pnianych przez spo(cid:239)eczno(cid:258)(cid:202) Node za pomoc(cid:200) standardowego systemu zarz(cid:200)dzania pakie- tami — npm. Ten system sprawi(cid:239), (cid:285)e JavaScript sta(cid:239) si(cid:218) jednym z profesjonalnych j(cid:218)zyków. Wprowadzenie do npm dla wszystkich osób, które dopiero poznaj(cid:200) tajniki Node, znajduje si(cid:218) pod adresem https://docs.npmjs.com/. Strumienie W swojej ksi(cid:200)(cid:285)ce J(cid:218)zyk C++. Kompendium wiedzy. Wydanie IV Bjarne Stroustrup wyja(cid:258)nia: Projektowanie i implementacja ogólnego mechanizmu wej(cid:258)cia-wyj(cid:258)cia dla j(cid:218)zyka progra- mowania jest notorycznie trudne. (…) Mechanizm wej(cid:258)cia-wyj(cid:258)cia powinien by(cid:202) (cid:239)atwy, wygodny i bezpieczny w u(cid:285)yciu, wydajny i elastyczny, a co najwa(cid:285)niejsze, powinien by(cid:202) kompletny. Nie powinno nikogo dziwi(cid:202), (cid:285)e zespó(cid:239) projektuj(cid:200)cy Node bardzo mocno skupi(cid:239) si(cid:218) na zapew- nieniu wydajnego i (cid:239)atwego w u(cid:285)yciu wej(cid:258)cia-wyj(cid:258)cia. Poprzez symetryczny i prosty interfejs, który obs(cid:239)uguje bufory danych i zdarzenia strumieni, aby nie musia(cid:239) si(cid:218) tym zajmowa(cid:202) programi- sta, modu(cid:239) Stream z Node to zalecany sposób zarz(cid:200)dzania synchronicznymi strumieniami danych zarówno w modu(cid:239)ach wewn(cid:218)trznych, jak i w modu(cid:239)ach, które programista tworzy samodzielnie. Bardzo dobre wprowadzenie do modu(cid:239)u Stream znajduje si(cid:218) pod adresem https://github.com/ substack/stream-handbook. Dokumentacja Node dotycz(cid:200)ca tego tematu znajduje si(cid:218) pod adresem https://nodejs.org/api/stream.html. Strumie(cid:241) w Node to po prostu ci(cid:200)g bajtów lub jak kto woli, ci(cid:200)g znaków. Na ka(cid:285)dym etapie strumie(cid:241) zawiera bufor bajtów, a ten bufor mo(cid:285)e mie(cid:202) d(cid:239)ugo(cid:258)(cid:202) zero lub wi(cid:218)cej bajtów. Poniewa(cid:285) ka(cid:285)dy znak w strumieniu jest dobrze zdefiniowany i poniewa(cid:285) ka(cid:285)dy typ danych cyfro- wych mo(cid:285)na wyrazi(cid:202) bajtami, ka(cid:285)d(cid:200) cz(cid:218)(cid:258)(cid:202) strumienia mo(cid:285)na przekierowa(cid:202) lub przes(cid:239)a(cid:202) potokiem do dowolnego innego strumienia. Poszczególne fragmenty strumienia mog(cid:200) trafi(cid:202) do ró(cid:285)nych obs(cid:239)uguj(cid:200)cych je funkcji. W ten sposób interfejs wej(cid:258)ciowy i wyj(cid:258)ciowy strumienia jest zarówno elastyczny, jak i przewidywalny, a co równie wa(cid:285)ne, daje si(cid:218) (cid:239)atwo (cid:239)(cid:200)czy(cid:202) w wi(cid:218)ksze ca(cid:239)o(cid:258)ci. Poza zdarzeniami system Node znany jest w(cid:239)a(cid:258)nie z bardzo intensywnego wykorzystania stru- mieni. Bazuj(cid:200)c na pomy(cid:258)le budowania aplikacji z wielu mniejszych procesów emituj(cid:200)cych zdarze- nia lub reaguj(cid:200)cych na nie, kilka modu(cid:239)ów wej(cid:258)cia-wyj(cid:258)cia z Node wykorzystuje w(cid:239)a(cid:258)nie stru- mienie. Gniazda sieciowe, odczyt i zapis plików, obs(cid:239)uga standardowego wyj(cid:258)cia i wej(cid:258)cia, obs(cid:239)uga Zlib itp. to wszystko producenci lub konsumenci danych, których mo(cid:285)na (cid:239)atwo po(cid:239)(cid:200)czy(cid:202) w wi(cid:218)ksz(cid:200) ca(cid:239)o(cid:258)(cid:202) dzi(cid:218)ki abstrakcyjnemu interfejsowi Stream. Zauwa(cid:285) tu bardzo du(cid:285)e podobie(cid:241)- stwo do potoków Unix. 32 Poleć książkęKup książkę Rozdzia(cid:225) 1. • Doceni(cid:252) Node Pi(cid:218)(cid:202) ró(cid:285)nych klas bazowych wykorzystuje abstrakcyjny interfejs Stream: Readable, Writable, Duplex, Transform i PassThrough. Ka(cid:285)da z klas bazowych dziedziczy po EventEmitter, czyli interfej- sie umo(cid:285)liwiaj(cid:200)cym zg(cid:239)aszanie zdarze(cid:241) i pod(cid:239)(cid:200)czanie procedur ich obs(cid:239)ugi. Strumienie w Node to strumienie zdarzeniowe, a przesy(cid:239) danych mi(cid:218)dzy procesami odbywa si(cid:218) w(cid:239)a(cid:258)nie za pomoc(cid:200) strumieni. Poniewa(cid:285) strumienie mo(cid:285)na (cid:239)atwo (cid:239)(cid:200)czy(cid:202) w (cid:239)a(cid:241)cuchy dzia(cid:239)a(cid:241), stanowi(cid:200) jedno z podsta- wowych narz(cid:218)dzi programisty Node. Warto, aby(cid:258) jako programista wiedzia(cid:239), czym s(cid:200) strumienie i jak zosta(cid:239)y zaimplementowane w Node, poniewa(cid:285) b(cid:218)dziemy z nich bardzo intensywnie korzysta(cid:202) w dalszej cz(cid:218)(cid:258)ci ksi(cid:200)(cid:285)ki. Wykorzystanie JavaScript na ka(cid:285)dym etapie projektu maksymalizuje dobre efekty JavaScript sta(cid:239) si(cid:218) j(cid:218)zykiem wszechstronnym. Oczywi(cid:258)cie istniej(cid:200) systemy wykonawcze j(cid:218)zyka w ka(cid:285)dej przegl(cid:200)darce internetowej. V8, interpreter JavaScript wykorzystywany przez Node, to ten sam interpreter, który znajduje si(cid:218) w przegl(cid:200)darce Chrome firmy Google. Sam j(cid:218)zyk poszed(cid:239) nawet dalej i obejmuje obecnie swoim zasi(cid:218)giem zarówno warstw(cid:218) klienck(cid:200), jak i war- stw(cid:218) serwerow(cid:200) stosu oprogramowania. JavaScriptu u(cid:285)ywa si(cid:218) do odpytywania bazy danych CouchDB, do realizacji operacji odwzorowanie-redukcja w MongoDB, a nawet do znajdowania kolekcji w ElasticSearch. Bardzo popularny format danych JSON (ang. JavaScript Object Notation) tak naprawd(cid:218) reprezentuje dane jako obiekty JavaScript. Gdy w jednej aplikacji u(cid:285)ywa si(cid:218) ró(cid:285)nych j(cid:218)zyków, wzrasta koszt prze(cid:239)(cid:200)czania kontekstu. Je(cid:258)li system sk(cid:239)ada si(cid:218) z cz(cid:218)(cid:258)ci opisywanych ró(cid:285)nymi j(cid:218)zykami, architektur(cid:218) systemu znacznie trudniej opisa(cid:202), zrozumie(cid:202) i rozszerzy(cid:202). Je(cid:258)li poszczególne cz(cid:218)(cid:258)ci mówi(cid:200) inaczej, potrzebne s(cid:200) kosztowne mechanizmy t(cid:239)umacz(cid:200)ce. Nieefektywno(cid:258)(cid:202) zrozumienia wszystkich elementów prowadzi do zwi(cid:218)kszenia kosztów i powsta- wania bardziej wra(cid:285)liwych systemów. Cz(cid:239)onkowie zespo(cid:239)u programistycznego musz(cid:200) dobrze zna(cid:202) wszystkie j(cid:218)zyki lub musz(cid:200) by(cid:202) podzieleni zadaniowo, co zwi(cid:218)ksza koszty szkole(cid:241) lub zna- lezienia dobrych programistów. Gdy szczegó(cid:239)y dzia(cid:239)ania istotnej cz(cid:218)(cid:258)ci systemu znane s(cid:200) tylko kilku in(cid:285)ynierom, zmniejszy si(cid:218) poziom wspó(cid:239)pracy w zespole, co zwi(cid:218)kszy koszt aktualizacji i uczyni je trudniejszymi, a tak(cid:285)e podatniejszymi na b(cid:239)(cid:218)dy. Jakie nowe mo(cid:285)liwo(cid:258)ci mog(cid:200) si(cid:218) pojawi(cid:202), gdy te trudno(cid:258)ci uda si(cid:218) zredukowa(cid:202), a nawet wy- eliminowa(cid:202)? 33 Poleć książkęKup książkę Node.js. Projektowanie, wdra(cid:298)anie i utrzymywanie aplikacji Zamiana kodu Poniewa(cid:285) cz(cid:218)(cid:258)(cid:202) kliencka i serwerowa mówi tym samym j(cid:218)zykiem, mog(cid:200) wspó(cid:239)dzieli(cid:202) pewne cz(cid:218)(cid:258)ci kodu. Je(cid:258)li budujesz aplikacj(cid:218) internetow(cid:200), otwiera to bardzo interesuj(cid:200)ce (i unikatowe) mo(cid:285)liwo(cid:258)ci. Rozwa(cid:285)my aplikacj(cid:218), która umo(cid:285)liwia klientowi wykonywanie zmian w innym (cid:258)rodowisku. Narz(cid:218)dzie to daje programi(cid:258)cie mo(cid:285)liwo(cid:258)(cid:202) zmiany kodu JavaScript nap(cid:218)dzaj(cid:200)cego witryn(cid:218) inter- netow(cid:200) i pozwala na zobaczenie tej zmiany przez inne klienty w czasie rzeczywistym. Aplikacja musi jednak w jaki(cid:258) sposób zamieni(cid:202) kod dzia(cid:239)aj(cid:200)cy w wielu ró(cid:285)nych przegl(cid:200)darkach. Jednym ze sposobów jest zawarcie zmiany w funkcji przekszta(cid:239)caj(cid:200)cej, przekazanie tej funkcji do wszystkich pod(cid:239)(cid:200)czonych klientów i wykonanie jej w lokalnym (cid:258)rodowisku, aby uzyska(cid:202) wersj(cid:218) kanoniczn(cid:200). Gdy aplikacja (cid:283)r
Pobierz darmowy fragment (pdf)

Gdzie kupić całą publikację:

Node.js. Projektowanie, wdrażanie i utrzymywanie aplikacji
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ą: