Dlaczego Node.js jest jednowątkowy? [Zamknięte]


255

W serwerach opartych na PHP (lub Java / ASP.NET / Ruby) każde żądanie klienta jest tworzone w nowym wątku. Ale w Node.js wszyscy klienci działają w tym samym wątku (mogą nawet współużytkować te same zmienne!) Rozumiem, że operacje We / Wy są oparte na zdarzeniach, więc nie blokują głównej pętli wątku.

Nie rozumiem, DLACZEGO autor Node wybrał go jako jednowątkowy? To utrudnia. Na przykład nie mogę uruchomić funkcji intensywnie wykorzystującej procesor, ponieważ blokuje ona główny wątek (a nowe żądania klientów są blokowane), więc muszę zrestartować proces (co oznacza, że ​​muszę utworzyć osobny plik JavaScript i wykonać inny proces węzła na to). Jednak w PHP procesory intensywne nie blokują innych klientów, ponieważ jak wspomniałem, każdy klient ma inny wątek. Jakie są jego zalety w porównaniu do wielowątkowych serwerów sieciowych?

Uwaga: korzystałem z klastrowania, aby obejść ten problem, ale to nie jest ładne.


12
Niedawno obejrzałem dobre wideo (29 minut) wyjaśniające niektóre teorie stojące za Node. Myślę nawet, że facet mówi o zadaniach intensywnie wykorzystujących procesor i krótko jak sobie z nimi poradzić: youtube.com/watch?v=L0pjVcIsU6A
whirlwin

24
Możesz to wiedzieć, ale dla jasności Node.js nie jest jednowątkowy. Twój kod JavaScript działa jednowątkowo, ale operacje IO i inne rzeczy, które wtyczki mogą zrobić, wyczerpują się z puli wątków. Node.js daje wiele korzyści z wielowątkowości bez konieczności radzenia sobie z wielowątkowym kodem. Ponadto autorzy JavaScript nie wybrali jednowątkowego charakteru JavaScript. Nie mogę wymyślić sposobu, w jaki JS mógłby działać w kontekście wielowątkowym, ale nawet gdyby tak było, V8 nie jest napisane w ten sposób, co jest używane przez Node.js jako silnik JavaScript.
Brad

5
PHP jest bardziej jedno-wątkowy niż JavaScript. Prawdopodobnie myślisz o modułach serwera, takich jak FastCGI lub mod_php. W rzeczywistości porównujesz Node.js z Apache, Nginx lub IIS - nie z PHP, Java ani Ruby.
Álvaro González

34
Węzeł nie jest jednowątkowy. To popularne nieporozumienie. Nawet proste node -e 'setTimeout(()=>{},1000);' & ps -T h $! | wc -l; kill $!wyświetla pięć wątków w moim systemie. Główna pętla zdarzeń jest jednowątkowa (nie miałaby większego sensu, gdyby tak nie było), ale Węzeł jest mocno wielowątkowy i możesz pisać wielowątkowe aplikacje jednoprocesowe, jeśli chcesz. Chciałbym napisać wyczerpującą odpowiedź na ten temat, ale niektóre osoby postanowiły zamknąć twoje pytanie, więc nie mogę. Głosuję za ponownym otwarciem. Jeśli otrzyma więcej głosów i zostanie ponownie otwarty, to proszę wspomnieć o mnie w komentarzu.
rsp

2
@rsp dziękuję za komentarz, ale w głównym wątku miałem na myśli, że nie dotyczy on operacji we / wy. jeśli robisz coś powiązanego z procesorem, np. dużą pętlę for, która coś robi, serwer przestaje przetwarzać połączenia. co oznacza, że ​​serwer jest w tej chwili bezużyteczny. więc używamy hacków takich jak klastry tylko po to, aby zrobić coś tak prostego zamiast nieodłącznie wątkować każde połączenie jak większość serwerów. jxcore.com próbowało rozwiązać ten problem, ale potem używa specjalnych / zmodyfikowanych wtyczek węzłów, co w zasadzie sprawia, że ​​nie nadaje się dla mnie.
foreyez

Odpowiedzi:


292

Plik Node.js został utworzony jawnie jako eksperyment w przetwarzaniu asynchronicznym. Teoria polegała na tym, że przetwarzanie asynchroniczne w jednym wątku może zapewnić większą wydajność i skalowalność przy typowych obciążeniach sieciowych niż typowa implementacja oparta na wątkach.

I wiesz co? Moim zdaniem ta teoria została potwierdzona. Aplikacja node.js, która nie wykonuje zadań intensywnie wykorzystujących procesor, może uruchamiać tysiące równoczesnych połączeń niż Apache, IIS lub inne serwery oparte na wątkach.

Jednowątkowa, asynchroniczna natura komplikuje sprawy. Ale czy naprawdę uważasz, że jest to bardziej skomplikowane niż wątki? Jeden warunek wyścigu może zrujnować cały miesiąc! Lub opróżnij pulę wątków z powodu jakiegoś ustawienia i obserwuj, jak czas reakcji powoli spada na indeksowanie! Nie wspominając o zakleszczeniach, priorytetowych inwersjach i wszystkich innych wahaniach, które towarzyszą wielowątkowości.

Ostatecznie nie sądzę, by było ogólnie lepiej czy gorzej; jest inny, a czasem lepszy, a czasem nie. Użyj odpowiedniego narzędzia do pracy.


26
Ale serwery sieciowe zwykle wykonują DUŻO dużo rzeczy intensywnie obciążających procesor, nie jest to tylko pobieranie bazy danych. Musimy przetworzyć to, co pobieramy, i zrobić dużo logiki biznesowej dużo czasu, zanim podamy to klientowi.
foreyez

22
Po prostu spawnuj pracowników, cóż! To cała sprawa z Node.js. Ciężkie rzeczy mogą działać w innym procesie, a ich przetworzenie powoduje lekkie oddzwonienie.
MaiaVictor

7
Problem polega na tym, że na pracownika działa proces na poziomie systemu operacyjnego. Zobaczysz go za pomocą polecenia „ps”. Oznacza to, że potencjalnie mogą to być tysiące procesów uruchomionych jednocześnie na maszynie - to szalone!
foreyez

9
@foreyez, Nie potrzebujesz procesu na użytkownika. Masz wybór sposobu podziału obciążenia. Ponadto, nie wszyscy robią mnóstwo rzeczy intensywnie wykorzystujących procesor. Węzeł jest narzędziem do pracy ... może nie do twojej pracy, ale do wielu rodzajów pracy.
Brad

15
Właściwie chciałbym, aby @foreyez utworzył kopię zapasową tego stwierdzenia, że ​​„serwery sieciowe zwykle ALOT (sic) rzeczy intensywnie wykorzystujących procesor”. Z mojego doświadczenia wynika, że ​​nie. A może moja definicja „intensywnego procesora” różni się od jego. Konwersja danych produktu na interfejs użytkownika nie wymaga procesora, nie oblicza zamówień ani tym podobnych. Większość sieci jest dość transakcyjna. Rzeczy wymagające dużej mocy procesora to między innymi konwertowanie filmów, konwertowanie formatów obrazów itp. Wiele z tego wynika z operacji we / wy plików, które w rzeczywistości węzeł radzi sobie całkiem nieźle. I ułatwia odciążenie do innego procesu poświęconego konwersji.
Paul

62

Problem z modelem „jeden wątek na żądanie” dla serwera polega na tym, że nie skalują się one dobrze dla kilku scenariuszy w porównaniu do modelu wątku pętli zdarzeń.

Zazwyczaj w scenariuszach intensywnych we / wy żądania spędzają większość czasu, czekając na zakończenie operacji we / wy. W tym czasie w modelu „jeden wątek na żądanie” zasoby powiązane z wątkiem (takie jak pamięć) są nieużywane, a pamięć jest czynnikiem ograniczającym. W modelu pętli zdarzeń wątek pętli wybiera następne zdarzenie (zakończone we / wy) do obsłużenia. Wątek jest więc zawsze zajęty (oczywiście jeśli poprawnie go zaprogramujesz).

Model pętli zdarzeń, ponieważ wszystkie nowe rzeczy wydają się błyszczące, a rozwiązanie wszystkich problemów, ale który model będzie używany, będzie zależeć od scenariusza, z którym trzeba się zmierzyć. Jeśli masz intensywny scenariusz we / wy (np. Serwer proxy), model podstawowy zdarzenia będzie rządził, podczas gdy scenariusz intensywny z małą liczbą równoległych procesów będzie działał najlepiej z modelem opartym na wątkach.

W prawdziwym świecie większość scenariuszy będzie trochę w środku. Będziesz musiał zrównoważyć rzeczywistą potrzebę skalowalności ze złożonością programistyczną, aby znaleźć odpowiednią architekturę (np. Mieć bazę zdarzeń opartą na zdarzeniu, która deleguje się do zaplecza dla zadań intensywnie wykorzystujących procesor. wynik). Podobnie jak w przypadku każdego systemu rozproszonego, wymaga on trochę wysiłku, aby działał.

Jeśli szukasz srebrnej kuli, która bez problemu zmieści się w każdym scenariuszu, skończysz z kulą w stopie.


8
Node.js jest ograniczony do przetwarzania tylko zdarzeń ze względu na brak obsługi wielowątkowości v8. Cóż, sam język javascript nie ma potrzebnych funkcji, więc każde wdrożenie będzie trudne. To, moim zdaniem, główny winowajca Node.js. W innych językach możesz wybrać, co chcesz. Lub niektóre hybrydy obu modeli, takie jak Java NIO.
FrameGrace

2
@Kazaag, Nowoczesne serwery WWW zrobić utrzymanie puli wątków. Nie tylko głupio spawnują nowy wątek na ładowanie strony. To są starsze serwery sieciowe.
Pacerier

1
@Pacerier Nigdy nie mówiłem, że nowy wątek jest spawnowany, ale każdy wątek jest przydzielany do jednego żądania, dopóki żądanie nie zostanie zakończone.
Kazaag

2
@Kazaag Zdecydowanie nie jest ogólną zasadą, że „każdy wątek jest przypisany do jednego żądania, dopóki żądanie nie zostanie zakończone”. Tj. W .Net (w tym przetwarzanie żądań HTTP) można i należy używać programowania asynchronicznego (opartego na zadaniach), a to zwolni wątki podczas oczekiwania na zakończenie operacji we / wy i innych operacji asynchronicznych. Dotyczy to również programowania na wysokim poziomie, tj. Kontrolerów MVC / API. W praktyce więc może być 20 oczekujących żądań HTTP, ale tylko jeden aktywny wątek.
user3285954,

29

Krótko mówiąc, węzeł czerpie z wersji V8, która jest wewnętrznie jednowątkowa. Istnieją sposoby obejścia ograniczeń dla zadań intensywnie wykorzystujących procesor.

W pewnym momencie (0.7) autorzy próbowali wprowadzić izolaty jako sposób implementacji wielu wątków obliczeniowych, ale ostatecznie zostali usunięci: https://groups.google.com/forum/#!msg/nodejs/zLzuo292hX0/F7gqfUiKi2sJ


Czy masz więcej informacji na temat tego „izolatu”?
Pacerier
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.