Node.js
Node.js

Follow

Feb 24, 2017 – 14 min read

Ten artykuł pochodzi od Tomislava Capana, konsultanta technicznego i entuzjasty Node.js. Tomislav pierwotnie opublikował to w sierpniu 2013 r. na blogu Toptal – oryginalny post można znaleźć tutaj; blog został nieco zaktualizowany. Poniższy temat jest oparty na opinii i doświadczeniach tego autora.

Rosnąca popularność JavaScriptu przyniosła ze sobą wiele zmian, a oblicze tworzenia stron internetowych jest dziś dramatycznie różne. Rzeczy, które możemy obecnie robić w sieci z JavaScriptem działającym na serwerze, jak również w przeglądarce, były trudne do wyobrażenia zaledwie kilka lat temu, lub były zamknięte w środowiskach piaskownicowych, takich jak Flash lub aplety Java.

Przed zagłębieniem się w Node.js, możesz chcieć przeczytać o korzyściach płynących z używania JavaScript w całym stosie, który ujednolica język i format danych (JSON), pozwalając na optymalne ponowne wykorzystanie zasobów deweloperskich. Ponieważ jest to bardziej zaleta JavaScriptu niż konkretnie Node.js, nie będziemy jej tutaj zbytnio omawiać. Ale jest to kluczowa zaleta włączenia Node.js do Twojego stosu.

Node.js jest środowiskiem uruchomieniowym JavaScript zbudowanym na silniku V8 JavaScript w Chrome. Warto zauważyć, że Ryan Dahl, twórca Node.js, miał na celu stworzenie stron internetowych w czasie rzeczywistym z funkcją push, „zainspirowanych aplikacjami takimi jak Gmail”. W Node.js dał programistom narzędzie do pracy w paradygmacie non-blocking, event-driven I/O.

Jednym zdaniem: Node.js błyszczy w aplikacjach internetowych działających w czasie rzeczywistym, wykorzystujących technologię push przez websockets. Co jest w tym takiego rewolucyjnego? Otóż, po ponad 20 latach funkcjonowania stateless-web opartego na paradygmacie stateless request-response, w końcu mamy aplikacje webowe z dwukierunkowymi połączeniami w czasie rzeczywistym, gdzie zarówno klient jak i serwer mogą inicjować komunikację, co pozwala im na swobodną wymianę danych.

Jest to wyraźny kontrast z typowym paradygmatem web response, gdzie klient zawsze inicjuje komunikację. Dodatkowo, wszystko to jest oparte na otwartym stosie sieciowym (HTML, CSS i JS) działającym na standardowym porcie 80.

Można by argumentować, że mieliśmy to od lat w formie Flasha i apletów Java – ale w rzeczywistości były to tylko środowiska piaskownicowe używające sieci jako protokołu transportowego do dostarczenia do klienta. Dodatkowo, były one uruchamiane w izolacji i często działały na niestandardowych portach, co mogło wymagać dodatkowych uprawnień i tym podobnych.

Wraz ze wszystkimi swoimi zaletami, Node.js odgrywa teraz krytyczną rolę w stosie technologicznym wielu wysoko postawionych firm, które polegają na jego unikalnych korzyściach. Fundacja Node.js skonsolidowała wszystkie najlepsze przemyślenia na temat tego, dlaczego przedsiębiorstwa powinny rozważyć Node.js w krótkiej prezentacji, którą można znaleźć na stronie Node.js Foundation’s Case Studies.

W tym poście omówię nie tylko to, jak te zalety są osiągane, ale także dlaczego możesz chcieć używać Node.js – i dlaczego nie – używając niektórych klasycznych modeli aplikacji internetowych jako przykładów.

Jak to działa?

Główna idea Node.js: użyj nieblokującego, sterowanego zdarzeniami wejścia/wyjścia, aby pozostać lekkim i wydajnym w obliczu aplikacji intensywnie przetwarzających dane w czasie rzeczywistym, które działają na rozproszonych urządzeniach.

To dużo powiedziane.

To, co to naprawdę oznacza, to fakt, że Node.js nie jest nową platformą, która zdominuje świat tworzenia stron internetowych. Zamiast tego, jest to platforma, która wypełnia konkretną potrzebę. I zrozumienie tego jest absolutnie niezbędne. Zdecydowanie nie chcesz używać Node.js do operacji intensywnie wykorzystujących procesor; w rzeczywistości, używanie go do ciężkich obliczeń unieważni prawie wszystkie jego zalety. Gdzie Node.js naprawdę błyszczy jest w budowaniu szybkich, skalowalnych aplikacji sieciowych, ponieważ jest w stanie obsłużyć ogromną liczbę jednoczesnych połączeń z wysoką przepustowością, co równa się wysokiej skalowalności.

Jak to działa pod maską jest całkiem interesujące. W porównaniu z tradycyjnymi technikami web-serwisu, gdzie każde połączenie (żądanie) powoduje powstanie nowego wątku, zajmującego systemową pamięć RAM i ostatecznie maxing-out na ilość dostępnej pamięci RAM, Node.js działa na pojedynczym wątku, używając nieblokujących wywołań I/O, co pozwala mu obsługiwać dziesiątki tysięcy współbieżnych połączeń (utrzymywanych w pętli zdarzeń).

*Zdjęcie zaczerpnięte z oryginalnego wpisu na blogu.

Szybka kalkulacja: zakładając, że każdy wątek potencjalnie ma ze sobą towarzyszące mu 2 MB pamięci, uruchomienie na systemie z 8 GB RAM stawia nas przy teoretycznym maksimum 4000 równoczesnych połączeń (obliczenia zaczerpnięte z artykułu Michaela Abernethy „Just what is Node.js?”, opublikowanego na IBM developerWorks w 2011 roku; niestety artykuł nie jest już dostępny), plus koszt przełączania kontekstu między wątkami. To jest scenariusz, z którym zazwyczaj masz do czynienia w tradycyjnych technikach web-servingowych. Unikając tego wszystkiego, Node.js osiąga skalowalność na poziomie ponad 1M jednoczesnych połączeń i ponad 600k jednoczesnych połączeń websockets.

Jest oczywiście kwestia dzielenia pojedynczego wątku pomiędzy wszystkie żądania klientów, i jest to potencjalna pułapka pisania aplikacji Node.js. Po pierwsze, ciężkie obliczenia mogłyby zadławić pojedynczy wątek Node’a i spowodować problemy dla wszystkich klientów (więcej na ten temat później), ponieważ przychodzące żądania byłyby zablokowane do czasu zakończenia wspomnianych obliczeń. Po drugie, programiści muszą być naprawdę ostrożni, aby nie pozwolić na wyjątek bulgoczący do głównej (najwyższej) pętli zdarzeń Node.js, która spowoduje zakończenie instancji Node.js (efektywnie crashując program).

Techniką używaną do unikania wyjątków bulgoczących na powierzchni jest przekazywanie błędów z powrotem do wywołującego jako parametrów wywołania zwrotnego (zamiast rzucania ich, jak w innych środowiskach). Nawet jeśli jakiś nieobsługiwany wyjątek zdoła wypłynąć na powierzchnię, opracowano narzędzia do monitorowania procesu Node.js i przeprowadzania niezbędnego odzyskiwania uszkodzonej instancji (chociaż prawdopodobnie nie będziesz w stanie odzyskać bieżącego stanu sesji użytkownika), najbardziej powszechnym jest moduł Forever, lub użycie innego podejścia z zewnętrznymi narzędziami systemowymi upstart i monit, lub nawet po prostu upstart.

npm: The Node Package Manager

Przy omawianiu Node.js, jedną z rzeczy, która zdecydowanie nie powinna być pominięta jest wbudowane wsparcie dla zarządzania pakietami za pomocą narzędzia npm, które jest domyślnie dołączone do każdej instalacji Node.js. Idea modułów npm jest dość podobna do Ruby Gems: zestaw publicznie dostępnych komponentów wielokrotnego użytku, dostępnych poprzez łatwą instalację za pośrednictwem repozytorium online, z zarządzaniem wersjami i zależnościami.

Pełną listę spakowanych modułów można znaleźć na stronie npm, lub uzyskać do nich dostęp za pomocą narzędzia npm CLI, które automatycznie instaluje się z Node.js. Ekosystem modułów jest otwarty dla wszystkich i każdy może opublikować swój własny moduł, który zostanie umieszczony w repozytorium npm. Krótkie wprowadzenie do npm można znaleźć w przewodniku dla początkujących, a szczegóły dotyczące publikowania modułów w npm Publishing Tutorial.

Kilka najbardziej przydatnych modułów npm to:

  • express – Express.js, inspirowany Sinatrą framework do tworzenia stron internetowych dla Node.js, i de-facto standard dla większości aplikacji Node.js obecnie.
  • hapi – bardzo modułowy i prosty w użyciu, skoncentrowany na konfiguracji framework do budowania aplikacji internetowych i usługowych
  • connect – Connect to rozszerzalny framework serwera HTTP dla Node.js, zapewniający zbiór wysokowydajnych „wtyczek” znanych jako middleware; służy jako podstawa dla Express.
  • socket.io i sockjs – komponent po stronie serwera dwóch najpopularniejszych obecnie komponentów websockets.
  • pug (dawniej Jade) – Jeden z popularnych silników szablonujących, inspirowany HAML-em, domyślny w Express.js.
  • mongodb i mongojs – wrappery MongoDB udostępniające API dla obiektowych baz danych MongoDB w Node.js.
  • redis – Biblioteka kliencka Redis.
  • lodash (underscore, lazy.js) – Pasek narzędziowy JavaScript. Underscore zapoczątkował grę, ale został obalony przez jednego ze swoich dwóch odpowiedników, głównie ze względu na lepszą wydajność i modułową implementację.
  • forever – Prawdopodobnie najbardziej powszechne narzędzie do zapewnienia, że dany skrypt węzła działa w sposób ciągły. Utrzymuje proces Node.js w produkcji w obliczu nieoczekiwanych awarii.
  • bluebird – W pełni funkcjonalna implementacja Promises/A+ o wyjątkowo dobrej wydajności
  • moment – Lekka biblioteka dat JavaScript do parsowania, walidacji, manipulacji i formatowania dat.

Lista ciągnie się dalej. Są tam tony naprawdę użytecznych pakietów, dostępnych dla wszystkich (bez urazy dla tych, które tu pominąłem).

Gdzie Node.js powinien być używany

Chat jest najbardziej typową aplikacją czasu rzeczywistego dla wielu użytkowników. Od IRC (w tamtych czasach), przez wiele zastrzeżonych i otwartych protokołów działających na niestandardowych portach, do możliwości wdrożenia wszystkiego dzisiaj w Node.js z websockets działającym na standardowym porcie 80.

Aplikacja czatu jest naprawdę przykładem sweet-spot dla Node.js: jest to lekka, o dużym natężeniu ruchu, intensywnie przetwarzająca dane (ale o niskim przetwarzaniu/obliczaniu) aplikacja, która działa na rozproszonych urządzeniach. Jest to również świetny przypadek użycia do nauki, ponieważ jest prosty, ale obejmuje większość paradygmatów, które kiedykolwiek użyjesz w typowej aplikacji Node.js.

Postarajmy się przedstawić, jak to działa.

W najprostszym scenariuszu, mamy pojedynczy chatroom na naszej stronie internetowej, gdzie ludzie przychodzą i mogą wymieniać wiadomości w sposób jeden do wielu (właściwie wszyscy). Na przykład, powiedzmy, że mamy trzy osoby na stronie internetowej, wszystkie podłączone do naszej tablicy wiadomości.

Po stronie serwera mamy prostą aplikację Express.js, która implementuje dwie rzeczy: 1) obsługę żądania GET '/’, która serwuje stronę internetową zawierającą zarówno tablicę wiadomości, jak i przycisk „Wyślij”, aby zainicjować wprowadzanie nowych wiadomości, oraz 2) serwer websockets, który nasłuchuje nowych wiadomości emitowanych przez klientów websocket.

Po stronie klienta mamy stronę HTML z kilkoma skonfigurowanymi handlerami, jeden dla zdarzenia kliknięcia przycisku „Wyślij”, który odbiera wiadomość wejściową i wysyła ją w dół websocket, a drugi, który nasłuchuje nowych wiadomości przychodzących na klienta websockets (tj, wiadomości wysłane przez innych użytkowników, które serwer chce, aby klient wyświetlił).

Kiedy jeden z klientów wysyła wiadomość, oto co się dzieje:

  • Przeglądarka łapie kliknięcie przycisku 'Wyślij’ poprzez JavaScript handler, pobiera wartość z pola wejściowego (tj…., tekst wiadomości), i wysyła wiadomość websocket przy użyciu klienta websocket podłączonego do naszego serwera (zainicjowanego podczas inicjalizacji strony internetowej).
  • Składnik po stronie serwera połączenia websocket odbiera wiadomość i przekazuje ją do wszystkich innych podłączonych klientów przy użyciu metody broadcast.
  • Wszyscy klienci otrzymują nową wiadomość jako wiadomość push poprzez składnik po stronie klienta websockets działający wewnątrz strony internetowej. Następnie odbierają treść wiadomości i aktualizują stronę internetową w miejscu, dołączając nową wiadomość do tablicy.

Obraz zaczerpnięty z oryginalnego bloga.

To jest najprostszy przykład. Aby uzyskać bardziej solidne rozwiązanie, można użyć prostego cache’u opartego na sklepie Redis. Lub w jeszcze bardziej zaawansowanym rozwiązaniu, kolejka komunikatów do obsługi routingu wiadomości do klientów i bardziej solidny mechanizm dostarczania, który może obejmować tymczasowe utraty połączenia lub przechowywanie wiadomości dla zarejestrowanych klientów, gdy są one w trybie offline. Ale niezależnie od ulepszeń, które wprowadzisz, Node.js nadal będzie działał w oparciu o te same podstawowe zasady: reagowanie na zdarzenia, obsługa wielu współbieżnych połączeń i utrzymywanie płynności wrażeń użytkownika.

API NA DACHU OBIEKTOWYM

Pomimo że Node.js naprawdę błyszczy w aplikacjach czasu rzeczywistego, to całkiem naturalnie nadaje się do eksponowania danych z obiektowych baz danych (np. MongoDB). Dane przechowywane w JSON pozwalają Node.js działać bez niedopasowania impedancji i konwersji danych.

Na przykład, jeśli używasz Rails, konwertowałbyś z JSON do modeli binarnych, a następnie eksponowałbyś je z powrotem jako JSON przez HTTP, gdy dane są konsumowane przez React.js, Angular.js, itp. lub nawet zwykłe wywołania jQuery AJAX. Dzięki Node.js możesz po prostu odsłonić swoje obiekty JSON za pomocą interfejsu API REST, aby klient mógł je skonsumować. Dodatkowo, nie musisz się martwić o konwersję między JSON a czymkolwiek innym podczas odczytu lub zapisu z bazy danych (jeśli używasz MongoDB). Podsumowując, możesz uniknąć potrzeby wielokrotnej konwersji, używając jednolitego formatu serializacji danych w kliencie, serwerze i bazie danych.

QUEUED INPUTS

Jeśli otrzymujesz dużą ilość równoczesnych danych, twoja baza danych może stać się wąskim gardłem. Jak pokazano powyżej, Node.js może łatwo obsłużyć współbieżne połączenia samodzielnie. Ale ponieważ dostęp do bazy danych jest operacją blokującą (w tym przypadku), napotykamy na problemy. Rozwiązaniem jest potwierdzenie zachowania klienta, zanim dane zostaną naprawdę zapisane do bazy danych.

Dzięki takiemu podejściu system zachowuje swoją responsywność przy dużym obciążeniu, co jest szczególnie przydatne, gdy klient nie potrzebuje solidnego potwierdzenia udanego zapisu danych. Typowe przykłady obejmują: rejestrowanie lub zapisywanie danych śledzących użytkownika, przetwarzanych w partiach i niewykorzystywanych do późniejszego czasu; a także operacje, które nie muszą być odzwierciedlane natychmiast (jak aktualizacja liczby „polubień” na Facebooku), gdzie ewentualna spójność (tak często stosowana w świecie NoSQL) jest akceptowalna.

Dane są kolejkowane przez jakiś rodzaj buforowania lub infrastruktury kolejkowania komunikatów (MQ) (np., RabbitMQ, ZeroMQ) i trawione przez oddzielny proces wsadowego zapisu do bazy danych, lub usługi backendu intensywnie przetwarzające dane obliczeniowe, napisane w lepiej działającej platformie do takich zadań. Podobne zachowanie może być zaimplementowane w innych językach/frameworkach, ale nie na tym samym sprzęcie, z tą samą wysoką, utrzymywaną przepustowością.

Zdjęcie zaczerpnięte z oryginalnego artykułu.

W skrócie: z Node, możesz zepchnąć zapisy do bazy danych na bok i zająć się nimi później, postępując tak, jakby się udało.

STREAMING DANYCH

W bardziej tradycyjnych platformach internetowych, żądania i odpowiedzi HTTP są traktowane jak odizolowane zdarzenia; w rzeczywistości są to strumienie. Ta obserwacja może być wykorzystana w Node.js, aby zbudować kilka fajnych funkcji. Na przykład, możliwe jest przetwarzanie plików w trakcie ich przesyłania, ponieważ dane przychodzą przez strumień i możemy je przetwarzać w trybie online. Można to zrobić dla kodowania audio lub wideo w czasie rzeczywistym i proksowania między różnymi źródłami danych (zobacz następną sekcję).

PROXY

Node.js jest łatwo zatrudniany jako proxy po stronie serwera, gdzie może obsługiwać dużą liczbę jednoczesnych połączeń w sposób nieblokujący. Jest to szczególnie przydatne do proksowania różnych usług o różnych czasach odpowiedzi lub zbierania danych z wielu punktów źródłowych.

Przykład: rozważ aplikację po stronie serwera komunikującą się z zasobami stron trzecich, pobierającą dane z różnych źródeł lub przechowującą zasoby takie jak obrazy i filmy w usługach chmurowych stron trzecich.

Pomimo że istnieją dedykowane serwery proxy, użycie Node zamiast nich może być pomocne, jeśli twoja infrastruktura proksowania nie istnieje lub jeśli potrzebujesz rozwiązania dla lokalnego rozwoju. Rozumiem przez to, że mógłbyś zbudować aplikację po stronie klienta z serwerem deweloperskim Node.js dla aktywów i proxy/stubbing żądań API, podczas gdy w produkcji obsługiwałbyś takie interakcje za pomocą dedykowanej usługi proxy (nginx, HAProxy, itp.).

BROKERAGE – STOCK TRADER’S DASHBOARD

Powróćmy do poziomu aplikacji. Innym przykładem, gdzie dominuje oprogramowanie desktopowe, ale może być łatwo zastąpione rozwiązaniem internetowym w czasie rzeczywistym, jest oprogramowanie handlowe maklerów, używane do śledzenia cen akcji, wykonywania obliczeń/analizy technicznej i tworzenia wykresów.

Przejście na rozwiązanie internetowe w czasie rzeczywistym pozwoliłoby maklerom łatwo zmieniać stacje robocze lub miejsca pracy. Wkrótce moglibyśmy zacząć widywać ich na plaży na Florydzie… lub Ibizie… lub Bali.

APPLICATION MONITORING DASHBOARD

Inny powszechny przypadek użycia, w którym Node-with-web-sockets pasuje idealnie: śledzenie odwiedzających stronę internetową i wizualizacja ich interakcji w czasie rzeczywistym. Możesz zbierać statystyki w czasie rzeczywistym od użytkownika, a nawet przenieść to na następny poziom, wprowadzając ukierunkowane interakcje z odwiedzającymi poprzez otwarcie kanału komunikacyjnego, gdy osiągną określony punkt w lejku – przykład tego można znaleźć z CANDDi.

Wyobraź sobie, jak mógłbyś poprawić swój biznes, gdybyś wiedział, co robią odwiedzający w czasie rzeczywistym – gdybyś mógł wizualizować ich interakcje. Dzięki dwukierunkowym gniazdom Node.js w czasie rzeczywistym, teraz możesz.

SYSTEM MONITORING DASHBOARD

Teraz odwiedźmy infrastrukturalną stronę rzeczy. Wyobraźmy sobie, na przykład, dostawcę SaaS, który chce zaoferować swoim użytkownikom stronę monitorującą usługi (na przykład stronę stanu GitHub). Dzięki pętli zdarzeń Node.js możemy stworzyć potężny, oparty na przeglądarce internetowej pulpit, który sprawdza statusy usług w sposób asynchroniczny i przesyła dane do klientów za pomocą websockets.

Zarówno wewnętrzne (wewnątrz firmy), jak i publiczne statusy usług mogą być raportowane na żywo i w czasie rzeczywistym za pomocą tej technologii. Pchnij ten pomysł nieco dalej i spróbuj wyobrazić sobie Network Operations Center (NOC) monitorujące aplikacje u operatora telekomunikacyjnego, dostawcy chmury/sieci/hostingu lub jakiejś instytucji finansowej, wszystkie uruchomione na otwartym stosie internetowym wspieranym przez Node.js i websockets zamiast Java i/lub Java Applets.

Uwaga: Nie próbuj budować systemów hard real-time w Node.js (tj. systemów wymagających stałych czasów odpowiedzi). Erlang jest prawdopodobnie lepszym wyborem dla tej klasy aplikacji.

SERVER-SIDE WEB APPLICATIONS

Node.js z Express.js może być również używany do tworzenia klasycznych aplikacji internetowych po stronie serwera. Jednakże, chociaż jest to możliwe, ten paradygmat żądanie-odpowiedź, w którym Node.js przenosiłby wyrenderowany HTML, nie jest najbardziej typowym przypadkiem użycia. Istnieją argumenty za i przeciw takiemu podejściu. Oto kilka faktów do rozważenia:

Pros:

  • Jeśli twoja aplikacja nie ma żadnych obliczeń intensywnie obciążających procesor, możesz zbudować ją w Javascript od góry do dołu, nawet do poziomu bazy danych, jeśli używasz JSON przechowywania Object DB jak MongoDB. To znacznie ułatwia rozwój (w tym zatrudnianie).
  • Crawlery otrzymują w pełni renderowaną odpowiedź HTML, która jest o wiele bardziej przyjazna dla SEO niż, powiedzmy, Single Page Application lub aplikacja websockets uruchomiona na szczycie Node.js.

Konsekwencje:

  • Każde obliczenie intensywne dla CPU zablokuje responsywność Node.js, więc platforma wątkowa jest lepszym podejściem. Alternatywnie możesz spróbować skalowania obliczeń(*).
  • Używanie Node.js z relacyjną bazą danych jest nadal dość bolesne (zobacz poniżej, aby uzyskać więcej szczegółów). Zrób sobie przysługę i podnieś dowolne inne środowisko, takie jak Rails, Django lub ASP.Net MVC, jeśli próbujesz wykonywać operacje relacyjne.

(*) Alternatywą dla obliczeń intensywnych dla procesora jest stworzenie wysoce skalowalnego środowiska wspieranego przez MQ z przetwarzaniem back-end, aby zachować Node jako front-facing „urzędnik” do obsługi żądań klienta asynchronicznie.

SERVER-SIDE WEB APPLICATION WITH A RELATIONAL DATABASE BEHIND

Porównując Node.js z Express.js przeciwko Ruby on Rails, na przykład, istnieje czysta decyzja na korzyść tego ostatniego, jeśli chodzi o relacyjny dostęp do danych.

Relacyjne narzędzia DB dla Node.js są nadal dość słabo rozwinięte, w porównaniu z konkurencją. Z drugiej strony, Railsy automatycznie zapewniają konfigurację dostępu do danych zaraz po wyjęciu z pudełka, wraz z narzędziami wspierającymi migrację schematów DB i innymi klejnotami (kalambury zamierzone). Railsy i ich rówieśnicze frameworki mają dojrzałe i sprawdzone implementacje warstwy dostępu do danych Active Record lub Data Mapper, których będzie ci bardzo brakowało jeśli spróbujesz je zreplikować w czystym JavaScript.(*)

Jeszcze, jeśli jesteś naprawdę skłonny pozostać JS all-the-way, sprawdź Sequelize i Node ORM2.

(*) Możliwe i nierzadkie jest używanie Node.js wyłącznie jako publicznej fasady, przy zachowaniu back-endu Rails i jego łatwego dostępu do relacyjnego DB.

HEAVY SERVER-SIDE COMPUTATION/PROCESSING

Gdy chodzi o ciężkie obliczenia, Node.js nie jest najlepszą platformą. Nie, zdecydowanie nie chcesz budować serwera obliczeń Fibonacciego w Node.js. Ogólnie rzecz biorąc, każda operacja intensywnie wykonywana przez procesor unieważnia wszystkie korzyści związane z przepustowością, jakie Node oferuje dzięki swojemu sterowanemu zdarzeniami, nieblokującemu modelowi I/O, ponieważ wszelkie przychodzące żądania zostaną zablokowane, podczas gdy wątek jest zajęty przez twoje obliczenia numeryczne.

Jak stwierdzono wcześniej, Node.js jest jednowątkowy i używa tylko jednego rdzenia procesora. Jeśli chodzi o dodanie współbieżności na serwerze wielordzeniowym, jest trochę pracy wykonywanej przez zespół rdzenia Node w postaci modułu klastra. Możesz również uruchomić kilka instancji serwera Node.js dość łatwo za odwrotnym proxy przez nginx.

Z klastrem, nadal powinieneś odciążyć wszystkie ciężkie obliczenia do procesów tła napisanych w bardziej odpowiednim do tego środowisku i mając je komunikujące się przez serwer kolejki komunikatów, taki jak RabbitMQ.

Nawet jeśli twoje przetwarzanie tła może być początkowo uruchomione na tym samym serwerze, takie podejście ma potencjał do bardzo wysokiej skalowalności. Te usługi przetwarzania w tle mogą być łatwo rozprowadzane do oddzielnych serwerów robotniczych bez potrzeby konfigurowania obciążeń serwerów internetowych front-facing.

Oczywiście, używałbyś tego samego podejścia również na innych platformach, ale z Node.js dostajesz wysoką przepustowość, o której mówiliśmy, ponieważ każde żądanie jest małym zadaniem obsługiwanym bardzo szybko i efektywnie.

Wniosek

Przedyskutowaliśmy Node.js od teorii do praktyki, zaczynając od jego celów i ambicji, a kończąc na jego słodkich punktach i pułapkach. Kiedy ludzie napotykają problemy z Node, prawie zawsze sprowadzają się one do tego, że operacje blokujące są korzeniem wszelkiego zła – 99% niewłaściwych zastosowań Node jest tego bezpośrednią konsekwencją.

Pamiętaj: Node.js nigdy nie został stworzony, aby rozwiązać problem skalowania obliczeń. Został stworzony, aby rozwiązać problem skalowania I/O, co robi naprawdę dobrze.