Node.js działa na jednym wątku, a i tak nadąża
Klasyczny serwer daje każdemu użytkownikowi osobny wątek. Node robi wszystko w jednym i przy tysiącach połączeń bywa szybszy. Sekret nie jest skomplikowany — to kwestia tego, czym program zajmuje się przez większość czasu.
Kiedy ktoś pierwszy raz słyszy, że Node.js jest jednowątkowy, reaguje zwykle podobnie: przecież to musi być wolne. A jednak przy obsłudze wielu jednoczesnych połączeń Node często wygrywa z serwerami, które dla każdego użytkownika odpalają osobny wątek.
Kelner zamiast kucharzy
Wyobraź sobie restaurację. Model klasyczny: każdy gość dostaje własnego kelnera. Gość czyta menu przez pięć minut — kelner stoi i czeka. Stu gości to stu kelnerów, z których większość nic nie robi.
Node działa jak jeden bardzo sprawny kelner. Przyjmuje zamówienie, oddaje je do kuchni i natychmiast idzie do następnego stolika. Kiedy danie jest gotowe, kuchnia daje znak i kelner je zanosi. Jeden człowiek obsługuje całą salę, bo nigdy nie stoi bezczynnie.
Skąd bierze się ta oszczędność
Typowa aplikacja webowa spędza większość czasu na czekaniu — na odpowiedź z bazy danych, na plik z dysku, na zewnętrzne API. Samo liczenie zajmuje ułamek tego czasu.
Node zamiast czekać zapisuje sobie: „gdy baza odpowie, wykonaj tę funkcję" — i zajmuje się kolejnym żądaniem. Ta lista zadań do wykonania po nadejściu odpowiedzi to właśnie pętla zdarzeń. Wątek jest jeden, ale nie marnuje ani chwili.
Dodatkowo każdy wątek kosztuje pamięć i czas na przełączanie kontekstu. Tysiąc wątków to setki megabajtów zjedzone przez samą infrastrukturę. Tysiąc oczekujących zadań w Node to tysiąc niewielkich wpisów na liście.
Gdzie ten model przestaje działać
Skoro wątek jest jeden, to zadanie, które naprawdę liczy, blokuje wszystkich. Zmiana rozmiaru dużego zdjęcia, generowanie raportu PDF, kompresja wideo — przez te trzy sekundy żaden inny użytkownik nie zostanie obsłużony.
Node jest świetny do zadań, które głównie czekają. Do zadań, które głównie liczą, trzeba mu pomóc.
Rozwiązania są dwa i oba proste: przenieść ciężką robotę do osobnego procesu (kolejka zadań w tle) albo skorzystać z mechanizmu wątków roboczych. W typowej stronie czy sklepie problem pojawia się rzadko — bo prawie wszystko sprowadza się do odpytania bazy i złożenia odpowiedzi.
Kiedy warto po niego sięgnąć
- API i mikroserwisy — dużo krótkich żądań, mało liczenia.
- Czat, powiadomienia, aplikacje na żywo — setki otwartych połączeń praktycznie nic nie kosztują.
- Warstwa pośrednia — kiedy trzeba połączyć odpowiedzi z kilku zewnętrznych usług i podać je frontendowi w jednym kawałku.
- Jeden język na całym stosie — ten sam kod walidacji działa w przeglądarce i na serwerze.
Node nie jest szybszy dlatego, że jest magiczny. Jest szybszy dlatego, że nie każe komputerowi stać bezczynnie.
Komentarze (9)
-
Wojtek
Porównanie z kelnerem jest lepsze niż połowa dokumentacji. Wreszcie ktoś wytłumaczył pętlę zdarzeń bez rysowania kolejek i stosów.
Odpowiedz -
Wojtek
Porównanie z kelnerem jest lepsze niż połowa dokumentacji. Wreszcie ktoś wytłumaczył pętlę zdarzeń bez rysowania kolejek i stosów.
Odpowiedz -
Iwona
Ten akapit o blokowaniu wątku przy generowaniu PDF opisuje dokładnie to, co przydarzyło się nam w zeszłym miesiącu. Poszliśmy w kolejkę zadań i problem zniknął.
Odpowiedz -
Iwona
Ten akapit o blokowaniu wątku przy generowaniu PDF opisuje dokładnie to, co przydarzyło się nam w zeszłym miesiącu. Poszliśmy w kolejkę zadań i problem zniknął.
Odpowiedz -
devops_pl
Fajny tekst, ale przydałoby się coś więcej o worker threads. Może na drugą część?
Odpowiedz- Administrator autor bloga
Notujemy temat — worker threads i kolejki zadań zasługują na osobny wpis. W skrócie: worker threads do liczenia w tej samej aplikacji, osobna kolejka do zadań, które mogą poczekać i przetrwać restart.
Odpowiedz - Administrator autor bloga
Notujemy temat — worker threads i kolejki zadań zasługują na osobny wpis. W skrócie: worker threads do liczenia w tej samej aplikacji, osobna kolejka do zadań, które mogą poczekać i przetrwać restart.
Odpowiedz
-
-
devops_pl
Fajny tekst, ale przydałoby się coś więcej o worker threads. Może na drugą część?
Odpowiedz- Administrator autor bloga
Notujemy temat — worker threads i kolejki zadań zasługują na osobny wpis. W skrócie: worker threads do liczenia w tej samej aplikacji, osobna kolejka do zadań, które mogą poczekać i przetrwać restart.
Odpowiedz
-
Przeczytaj też
WebSocket w Node: kiedy strona ma odzywać się sama
Zwykły HTTP działa jak wysyłanie listów: klient pyta, serwer odpowiada. Przy czacie czy powiadomieniach to za mało — potrzebna jest linia telefoniczna, którą obie strony mogą się odezwać w dowolnym momencie. Od tego jest WebSocket.
Pięć wyrażeń regularnych, które warto mieć pod ręką
Wyrażenia regularne wyglądają jak przypadkowy zbiór znaków, dopóki nie rozłoży się ich na części. Oto pięć wzorców z codziennej pracy, rozebranych po kawałku.
Co się dzieje, gdy wpisujesz adres w przeglądarce
Między naciśnięciem Enter a pojawieniem się strony mija ułamek sekundy. W tym czasie dzieje się kilka rzeczy, które warto znać — choćby po to, żeby wiedzieć, gdzie szukać, kiedy strona się nie ładuje.
Robimy strony, które są szybkie nie tylko na papierze.
Poproś o darmową wycenę