Co byłoby lepsze w przypadku współbieżnych zadań na node.js? Włókna? Pracownicy sieciowi? lub Wątki?

111

Natknąłem się kiedyś na node.js i bardzo to lubię. Ale wkrótce okazało się, że bardzo brakowało mu możliwości wykonywania zadań intensywnie wykorzystujących procesor. Więc zacząłem googlować i otrzymałem te odpowiedzi, aby rozwiązać problem: Włókna, Webworkers i Wątki (thread-a-gogo). Który z nich jest mylący, a jeden z nich zdecydowanie musi być używany - w końcu jaki jest cel posiadania serwera, który jest po prostu dobry w IO i nic więcej? Potrzebne sugestie!

AKTUALIZACJA:

Myślałem o późnym spóźnieniu; potrzebuję tylko sugestii. Pomyślałem teraz o tym: Przeprowadźmy kilka wątków (używając thread_a_gogo lub może webworkers). Teraz, gdy potrzebujemy ich więcej, możemy tworzyć więcej. Ale proces tworzenia będzie ograniczony. (nie sugerowane przez system, ale prawdopodobnie z powodu kosztów ogólnych). Teraz, gdy przekroczymy limit, możemy rozwidlić nowy węzeł i zacząć tworzyć nad nim wątki. W ten sposób może to trwać, aż osiągniemy pewien limit (w końcu procesy również mają duży narzut). Po osiągnięciu tego limitu rozpoczynamy kolejkowanie zadań. Za każdym razem, gdy wątek zostanie zwolniony, zostanie mu przypisane nowe zadanie. W ten sposób może przebiegać sprawnie.

Więc o tym pomyślałem. Czy to dobry pomysł? Jestem trochę nowy w tym całym procesie i wątkach, więc nie mam w tym żadnej wiedzy. Prosimy o podzielenie się swoimi opiniami.

Dzięki. :)

Parth Thakkar
źródło
Uwaga: pracownicy są specyfikacją przeglądarki, a nie funkcją Javascript.
FredTheWebGuy
Cóż, widzę to. Moje pytanie dotyczyło node.js - kodu serwera, a nie strony klienta!
Parth Thakkar
Tylko wyjaśnienie - widzę, że pierwotne pytanie dotyczyło Webworkerów w NodeJs, co jest niemożliwe - NodeJs używa "Threads". Istnieje jednak moduł NodeJS, który umożliwia składnię WebWorker w środowisku wykonawczym NodeJs.
FredTheWebGuy

Odpowiedzi:

331

Węzeł ma zupełnie inny paradygmat i po prawidłowym ujęciu łatwiej jest dostrzec inny sposób rozwiązywania problemów. Nigdy nie potrzebujesz wielu wątków w aplikacji Node (1), ponieważ masz inny sposób robienia tego samego. Tworzysz wiele procesów; ale bardzo różni się od tego, na przykład jak działa Prefork mpm Apache Web Server.

Na razie pomyślmy, że mamy tylko jeden rdzeń procesora i opracujemy aplikację (na sposób Node) do wykonania jakiejś pracy. Naszym zadaniem jest przetworzenie dużego pliku zawierającego bajt po bajcie. Najlepszym sposobem dla naszego oprogramowania jest rozpoczęcie pracy od początku pliku i śledzenie go bajt po bajcie do końca.

- Hej, Hasan, przypuszczam, że jesteś nowicjuszem lub bardzo starą szkołą z czasów mojego dziadka !!! Dlaczego nie utworzysz kilku wątków i nie przyspieszysz tego?

- Och, mamy tylko jeden rdzeń procesora.

-- Więc co? Stwórz jakieś wątki człowieku, zrób to szybciej!

- To tak nie działa. Jeśli utworzę wątki, spowalniam je. Ponieważ będę dodawał dużo narzutów do systemu, aby przełączać się między wątkami, próbując dać im odpowiednią ilość czasu, a także wewnątrz mojego procesu, próbując komunikować się między tymi wątkami. Oprócz tych wszystkich faktów będę musiał również pomyśleć o tym, jak podzielę jedną pracę na wiele części, które można wykonać równolegle.

- Dobra, dobra, widzę, że jesteś biedny. Skorzystajmy z mojego komputera, który ma 32 rdzenie!

- Wow, jesteś niesamowity mój drogi przyjacielu, bardzo dziękuję. Doceniam to!

Następnie wracamy do pracy. Dzięki naszemu bogatemu przyjacielowi mamy teraz 32 rdzenie procesora. Zasady, których musimy przestrzegać, właśnie się zmieniły. Teraz chcemy spożytkować całe otrzymane bogactwo.

Aby korzystać z wielu rdzeni, musimy znaleźć sposób na podzielenie naszej pracy na części, które możemy obsługiwać równolegle. Gdyby to nie był Node, użylibyśmy do tego wątków; 32 wątki, po jednym na każdy rdzeń procesora. Jednak ponieważ mamy Node, stworzymy 32 procesy Node.

Wątki mogą być dobrą alternatywą dla procesów Node, a może nawet lepszym sposobem; ale tylko na konkretnym stanowisku, gdzie praca jest już zdefiniowana i mamy pełną kontrolę nad tym, jak ją wykonać. Poza tym w przypadku każdego innego rodzaju problemu, w którym praca pochodzi z zewnątrz w sposób, nad którym nie mamy kontroli i chcemy odpowiedzieć tak szybko, jak to możliwe, droga Node jest bezspornie lepsza.

- Hej, Hasan, nadal pracujesz jednowątkowo? Co jest z tobą nie tak, stary? Właśnie zapewniłem ci to, czego chciałeś. Nie masz już wymówek. Twórz wątki, spraw, by działały szybciej.

- Podzieliłem pracę na części i każdy proces będzie działał na jednym z tych elementów równolegle.

- Dlaczego nie tworzysz wątków?

- Przepraszam, nie sądzę, żeby to było użyteczne. Możesz zabrać swój komputer, jeśli chcesz?

- Nie okej, w porządku, po prostu nie rozumiem, dlaczego nie używasz nici?

- Dziękuję za komputer. :) Dzieliłem już pracę na części i tworzę równolegle procesy do pracy nad tymi kawałkami. Wszystkie rdzenie procesora zostaną w pełni wykorzystane. Mógłbym to zrobić z wątkami zamiast procesów; ale Node ma ten sposób i moja szefowa Parth Thakkar chce, żebym używał Node.

- Dobra, daj mi znać, jeśli potrzebujesz innego komputera. : p

Jeśli utworzę 33 procesy, zamiast 32, program planujący systemu operacyjnego będzie wstrzymywać wątek, uruchamiać drugi, pauzować po kilku cyklach, ponownie uruchamiać drugi ... To niepotrzebny narzut. Nie chcę tego. W rzeczywistości w systemie z 32 rdzeniami nie chciałbym nawet tworzyć dokładnie 32 procesów, 31 może być ładniejsze . Ponieważ nie tylko moja aplikacja będzie działać w tym systemie. Pozostawienie trochę miejsca na inne rzeczy może być dobre, zwłaszcza jeśli mamy 32 pokoje.

Myślę, że jesteśmy teraz po tej samej stronie, jeśli chodzi o pełne wykorzystanie procesorów do zadań intensywnie wykorzystujących procesor .

- Hmm, Hasan, przepraszam, że trochę z ciebie kpiłem. Myślę, że teraz rozumiem cię lepiej. Ale jest jeszcze coś, na co potrzebuję wyjaśnienia: po co to całe zamieszanie związane z prowadzeniem setek wątków? Wszędzie czytałem, że wątki są znacznie szybsze do tworzenia i głupie niż procesy rozwidlania? Rozwidlasz procesy zamiast wątków i myślisz, że jest to najwyższa wartość, jaką można uzyskać w Node. Czy zatem Node nie jest odpowiedni do tego rodzaju pracy?

- Bez obaw, ja też jestem spoko. Wszyscy tak mówią, więc myślę, że jestem przyzwyczajony do ich słuchania.

-- Więc? Węzeł nie nadaje się do tego?

- Węzeł doskonale się do tego nadaje, chociaż wątki też mogą być dobre. Jeśli chodzi o narzut tworzenia wątków / procesów; w przypadku rzeczy, które często powtarzasz, liczy się każda milisekunda. Jednak tworzę tylko 32 procesy i zajmie to niewielką ilość czasu. Stanie się to tylko raz. To nie ma znaczenia.

- Kiedy więc chcę tworzyć tysiące wątków?

- Nigdy nie chcesz tworzyć tysięcy wątków. Jednak w systemie wykonującym pracę pochodzącą z zewnątrz, na przykład serwer WWW przetwarzający żądania HTTP; jeśli używasz wątku do każdego żądania, utworzysz wiele wątków, wiele z nich.

- Węzeł jest jednak inny? Dobrze?

-- Tak, dokładnie. W tym miejscu Node naprawdę błyszczy. Podobnie jak wątek jest znacznie lżejszy niż proces, wywołanie funkcji jest znacznie lżejsze niż wątek. Węzeł wywołuje funkcje, zamiast tworzyć wątki. W przykładzie serwera WWW każde przychodzące żądanie powoduje wywołanie funkcji.

-- Hmm interesujące; ale możesz uruchomić tylko jedną funkcję w tym samym czasie, jeśli nie używasz wielu wątków. Jak to działa, gdy do serwera WWW dociera wiele żądań w tym samym czasie?

- Masz całkowitą rację co do tego, jak funkcje działają pojedynczo, nigdy dwie równolegle. Mam na myśli to, że w jednym procesie działa tylko jeden zakres kodu w danym momencie. Harmonogram systemu operacyjnego nie przychodzi i nie wstrzymuje tej funkcji i nie przełącza się na inną, chyba że wstrzyma proces, aby dać czas na inny proces, a nie inny wątek w naszym procesie. (2)

- W takim razie w jaki sposób proces może obsłużyć jednocześnie 2 żądania?

- Proces może obsłużyć dziesiątki tysięcy żądań jednocześnie, o ile nasz system ma wystarczające zasoby (pamięć RAM, sieć itp.). Sposób działania tych funkcji to KLUCZOWA RÓŻNICA.

- Hmm, czy powinienem być teraz podekscytowany?

- Może :) Węzeł uruchamia pętlę w kolejce. W tej kolejce są nasze zadania, tj. Połączenia, które zaczęliśmy przetwarzać przychodzące żądania. Najważniejszym punktem jest sposób, w jaki projektujemy nasze funkcje do działania. Zamiast zaczynać przetwarzanie żądania i zmuszać dzwoniącego do czekania, aż zakończymy pracę, szybko kończymy naszą funkcję po wykonaniu odpowiedniej ilości pracy. Kiedy dochodzimy do punktu, w którym musimy poczekać, aż inny komponent wykona jakąś pracę i zwróci nam wartość, zamiast czekać na to, po prostu kończymy naszą funkcję, dodając resztę pracy do kolejki.

- Brzmi zbyt skomplikowanie?

- Nie, nie, mogę brzmieć skomplikowanie; ale sam system jest bardzo prosty i ma sens.

Teraz chcę przestać cytować dialog między tymi dwoma programistami i zakończyć moją odpowiedź po ostatnim krótkim przykładzie działania tych funkcji.

W ten sposób robimy to, co normalnie zrobiłby OS Scheduler. W pewnym momencie wstrzymujemy naszą pracę i pozwalamy innym wywołaniom funkcji (jak inne wątki w środowisku wielowątkowym) działać, dopóki nie otrzymamy ponownie naszej tury. Jest to znacznie lepsze niż pozostawienie pracy harmonogramowi systemu operacyjnego, który próbuje poświęcić czas każdemu wątkowi w systemie. Wiemy, co robimy, znacznie lepiej niż OS Scheduler i oczekuje się, że przestaniemy, kiedy powinniśmy przestać.

Poniżej znajduje się prosty przykład, w którym otwieramy plik i czytamy go, aby popracować nad danymi.

Synchroniczny sposób:

Open File
Repeat This:    
    Read Some
    Do the work

Sposób asynchroniczny:

Open File and Do this when it is ready: // Our function returns
    Repeat this:
        Read Some and when it is ready: // Returns again
            Do some work

Jak widać, nasza funkcja prosi system o otwarcie pliku i nie czeka na jego otwarcie. Kończy się, zapewniając kolejne kroki po przygotowaniu pliku. Kiedy wracamy, Node uruchamia inne wywołania funkcji w kolejce. Po przejrzeniu wszystkich funkcji pętla zdarzeń przechodzi do następnej tury ...

Podsumowując, Node ma zupełnie inny paradygmat niż programowanie wielowątkowe; ale to nie znaczy, że czegoś brakuje. W przypadku zadania synchronicznego (w którym możemy zdecydować o kolejności i sposobie przetwarzania) działa tak samo jak wielowątkowa równoległość. W przypadku zadań przychodzących z zewnątrz, takich jak żądania do serwera, jest po prostu lepsze.


(1) Chyba że budujesz biblioteki w innych językach, takich jak C / C ++, w którym to przypadku nadal nie tworzysz wątków do dzielenia zadań. Do tego rodzaju pracy masz dwa wątki, z których jeden będzie kontynuował komunikację z Node, podczas gdy drugi będzie wykonywał prawdziwą pracę.

(2) W rzeczywistości każdy proces Node ma wiele wątków z tych samych powodów, o których wspomniałem w pierwszym przypisie. Jednak nie jest to sposób, w jaki 1000 wątków wykonuje podobne prace. Te dodatkowe wątki służą do akceptowania zdarzeń IO i obsługi komunikatów międzyprocesowych.

UPDATE (jako odpowiedź na dobre pytanie w komentarzach)

@Mark, dziękuję za konstruktywną krytykę. W paradygmacie Node nigdy nie powinieneś mieć funkcji, których przetwarzanie zajmuje zbyt dużo czasu, chyba że wszystkie inne wywołania w kolejce są zaprojektowane tak, aby były uruchamiane jedna po drugiej. W przypadku zadań kosztownych obliczeniowo, jeśli spojrzymy na obraz w całości, zobaczymy, że nie jest to kwestia „Czy powinniśmy używać wątków czy procesów?” ale pytanie „Jak możemy podzielić te zadania w dobrze wyważony sposób na pod-zadania, które możemy wykonywać równolegle, wykorzystując wiele rdzeni procesora w systemie?” Powiedzmy, że przetworzymy 400 plików wideo w systemie z 8 rdzeniami. Jeśli chcemy przetwarzać jeden plik na raz, potrzebujemy systemu, który będzie przetwarzał różne części tego samego pliku, w którym to przypadku być może wielowątkowy system jednoprocesowy będzie łatwiejszy do zbudowania i jeszcze bardziej wydajny. Nadal możemy do tego używać Node, uruchamiając wiele procesów i przesyłając komunikaty między nimi, gdy konieczne jest współdzielenie stanu / komunikacja. Jak powiedziałem wcześniej, podejście wieloprocesowe w Node toa także wielowątkowe podejście do tego rodzaju zadań; ale nie więcej. Ponownie, jak powiedziałem wcześniej, sytuacja, w której Node świeci, ma miejsce, gdy mamy te zadania przychodzące do systemu z wielu źródeł, ponieważ jednoczesne utrzymywanie wielu połączeń jest znacznie lżejsze w Node w porównaniu z wątkiem na połączenie lub procesem na połączenie system.

Jeśli chodzi o setTimeout(...,0)rozmowy; czasami może być wymagane zrobienie przerwy w czasochłonnym zadaniu, aby umożliwić połączeniom w kolejce udział w przetwarzaniu. Dzielenie zadań na różne sposoby może cię przed nimi uchronić; ale nadal nie jest to tak naprawdę hack, to tylko sposób, w jaki działają kolejki zdarzeń. Również użycie process.nextTickdo tego celu jest o wiele lepsze, ponieważ podczas używania setTimeoutobliczenia i sprawdzanie minionego czasu będą konieczne, a process.nextTickjest to po prostu to, czego naprawdę chcemy: „Hej zadanie, wróć na koniec kolejki, wykorzystałeś swój udział! "

hasanyasin
źródło
9
Niesamowity! Cholernie niesamowite! Podobał mi się sposób, w jaki odpowiedziałeś na to pytanie! :)
Parth Thakkar
48
Jasne :) Naprawdę nie mogę uwierzyć, że są tam wyjątkowo źli ludzie, którzy głosują w dół na ten artykuł z odpowiedzią! Pytający nazywa to „Cholernie niesamowite!” a autor książki proponuje mi napisanie na swojej stronie internetowej po obejrzeniu tego; ale niektórzy geniusze głosują w dół. Dlaczego nie podzielisz się swoją błyskotliwą intelektualną cechą i nie skomentujesz tego zamiast złośliwie i podstępnie przegłosować, co? Dlaczego coś miłego tak bardzo Ci przeszkadza? Dlaczego chcesz, aby coś pożytecznego nie dotarło do innych osób, które naprawdę mogą na tym skorzystać?
hasanyasin
9
To nie jest całkowicie uczciwa odpowiedź. A co z zadaniami wymagającymi dużej mocy obliczeniowej, w których nie możemy „szybko zakończyć” wywołania funkcji? Myślę, że niektórzy używają setTimeout(...,0)do tego hacków, ale użycie osobnego wątku w tym scenariuszu z pewnością byłoby lepsze?
mpen
3
@hasanyasin To najładniejsze wyjaśnienie dotyczące węzła, jakie do tej pory znalazłem! :)
Venemo
7
@Mark Ogólnie, jeśli jest to tak kosztowne obliczeniowo, istnieją opcje / moduły dla pracowników bieżnika / procesu ... Ogólnie rzecz biorąc, używam kolejki wiadomości i mam procesy robocze, które obsługują zadanie w czas od kolejki i wykonuj to zadanie. Pozwala to również na skalowanie do wielu serwerów. Zgodnie z tymi wytycznymi Substack ma wiele modułów ukierunkowanych na udostępnianie i skalowanie, na które można spojrzeć.
Tracker1
34

(Aktualizacja 2016: pracownicy sieci Web przechodzą do io.js - rozwidlenia Node.js Node.js v7 - patrz poniżej.)

(Aktualizacja 2017: Pracownicy sieciowi nie przechodzą do Node.js v7 ani v8 - patrz poniżej).

(Aktualizacja 2018: pracownicy sieci wchodząc v10.5.0 node.js Node - patrz poniżej).

Pewne wyjaśnienie

Po przeczytaniu powyższych odpowiedzi chciałbym zwrócić uwagę, że w robotach internetowych nie ma nic, co byłoby sprzeczne z filozofią JavaScript w ogóle, a Node w szczególności, jeśli chodzi o współbieżność. (Gdyby tak było, nie byłoby to nawet omawiane przez WHATWG, a tym bardziej zaimplementowane w przeglądarkach).

Możesz myśleć o programie roboczym sieci Web jako lekkiej mikrousłudze, do której dostęp jest uzyskiwany asynchronicznie. Żaden stan nie jest udostępniany. Nie ma problemów z blokowaniem. Nie ma blokowania. Nie jest wymagana synchronizacja. Podobnie jak w przypadku korzystania z usługi RESTful z programu Node, nie martwisz się, że jest ona teraz „wielowątkowa”, ponieważ usługa RESTful nie znajduje się w tym samym wątku co Twoja własna pętla zdarzeń. To tylko oddzielna usługa, do której uzyskujesz dostęp asynchronicznie i to jest najważniejsze.

To samo dotyczy pracowników internetowych. To tylko API do komunikacji z kodem, który działa w zupełnie innym kontekście i to, czy znajduje się w innym wątku, innym procesie, innej grupie cgr, strefie, kontenerze lub innej maszynie, jest całkowicie nieistotne, ze względu na ściśle asynchroniczne, nieblokujące API, ze wszystkimi danymi przekazanymi według wartości.

W rzeczywistości pracownicy sieciowi koncepcyjnie idealnie pasują do Node, który - o czym wiele osób nie jest świadomych - przypadkowo wykorzystuje wątki dość intensywnie i faktycznie „wszystko działa równolegle z wyjątkiem twojego kodu” - zobacz:

Ale pracownicy sieciowi nie muszą nawet być implementowani przy użyciu wątków. Możesz używać procesów, zielonych wątków, a nawet usług RESTful w chmurze - o ile używany jest interfejs API procesu roboczego. Całe piękno interfejsu API przekazującego komunikaty z semantyką wywołań według wartości polega na tym, że podstawowa implementacja jest prawie nieistotna, ponieważ szczegóły modelu współbieżności nie zostaną ujawnione.

Jednowątkowa pętla zdarzeń jest idealna do operacji związanych z we / wy. Nie działa tak dobrze w przypadku operacji związanych z procesorem, szczególnie tych długotrwałych. W tym celu musimy stworzyć więcej procesów lub użyć wątków. Zarządzanie procesami potomnymi i komunikacją między procesami w sposób przenośny może być dość trudne i często jest postrzegane jako przesada w przypadku prostych zadań, podczas gdy używanie wątków oznacza radzenie sobie z blokadami i problemami z synchronizacją, które są bardzo trudne do wykonania.

Często zalecane jest podzielenie długotrwałych operacji związanych z procesorem na mniejsze zadania (coś jak przykład w sekcji „Oryginalna odpowiedź” mojej odpowiedzi na Przyspieszenie setInterval ), ale nie zawsze jest to praktyczne i nie wykorzystuje więcej niż jeden rdzeń procesora.

Piszę to, aby wyjaśnić komentarze, które zasadniczo mówiły, że pracownicy sieci Web zostali stworzeni dla przeglądarek, a nie serwerów (zapominając, że w JavaScript można powiedzieć o prawie wszystkim).

Moduły węzłów

Istnieje kilka modułów, które mają dodawać Web Workers do Node:

Nie korzystałem z żadnego z nich, ale mam dwie szybkie obserwacje, które mogą być istotne: od marca 2015, node-webworker był ostatnio aktualizowany 4 lata temu, a node-webworker-wątki ostatnio aktualizowano miesiąc temu. Widzę również w przykładzie użycia węzłów-webworker-wątków, że można użyć funkcji zamiast nazwy pliku jako argumentu dla konstruktora Worker, co wydaje się powodować subtelne problemy, jeśli jest realizowane przy użyciu wątków współdzielących pamięć (chyba że function jest używane tylko w swojej metodzie .toString () i jest skompilowane w innym środowisku, w takim przypadku może być w porządku - muszę się temu dokładniej przyjrzeć, dzieląc się tutaj moimi obserwacjami).

Jeśli istnieje inny odpowiedni projekt, który implementuje interfejs API pracowników sieci Web w Node, zostaw komentarz.

Zaktualizuj 1

Nie znałem go jeszcze w czasie pisania, ale nawiasem mówiąc jeden dzień wcześniej pisałem tę odpowiedź Web Workers dodano io.js .

( io.js to rozwidlenie Node.js - zobacz: Dlaczego io.js zdecydowało się rozwidlić Node.js , wywiad InfoWorld z Mikealem Rogersem, aby uzyskać więcej informacji).

Nie tylko dowodzi, że w robotach internetowych nie ma nic, co jest sprzeczne z filozofią JavaScript w ogóle, a Node w szczególności w zakresie współbieżności, ale może to spowodować, że pracownicy sieci Web będą obywatelami pierwszej klasy w JavaScript po stronie serwera, takich jak io. js (i prawdopodobnie Node.js w przyszłości), tak jak jest już w JavaScript po stronie klienta we wszystkich nowoczesnych przeglądarkach .

Zaktualizuj 2

W aktualizacji 1 i moim tweecie odnosiłem się do żądania ściągnięcia io.js nr 1159, które teraz przekierowuje do Node PR # 1159, który został zamknięty 8 lipca i zastąpiony przez Node PR # 2133 - który jest nadal otwarty. W ramach tych żądań ściągnięcia toczy się dyskusja, która może dostarczyć bardziej aktualnych informacji o stanie pracowników sieci Web w io.js / Node.js.

Zaktualizuj 3

Najnowsze informacje - podziękowania dla NiCk Newman za zamieszczenie ich w komentarzach: Oto pracownicy: wstępne wdrożenie zatwierdzone przez Petkę Antonov z 6 września 2015 r., Które można pobrać i wypróbować w tym drzewie . Szczegółowe informacje można znaleźć w komentarzach NiCk Newman .

Zaktualizuj 4

Stan na maj 2016 r . Ostatnie uwagi dotyczące wciąż otwartego PR # 2133 - pracownicy: wstępne wdrożenie miało 3 miesiące. 30 maja Matheus Moreira poprosił mnie o opublikowanie aktualizacji tej odpowiedzi w komentarzach poniżej i zapytał o aktualny stan tej funkcji w komentarzach PR.

Pierwsze odpowiedzi w dyskusji PR były sceptyczne, ale później Ben Noordhuis napisał, że „Połączenie tego w takim czy innym kształcie jest na mojej liście rzeczy do zrobienia dla wersji 7”.

Wszystkie inne komentarze zdawały się potwierdzać to i od lipca 2016 r. Wydaje się, że Web Workers powinien być dostępny w następnej wersji Node , wersji 7.0, która ma zostać wydana w październiku 2016 r. (Niekoniecznie w formie tego dokładnego PR).

Podziękowania dla Matheusa Moreiry za wskazanie tego w komentarzach i ożywienie dyskusji na GitHubie.

Zaktualizuj 5

Od lipca 2016 r. Jest kilka modułów na npm, które wcześniej nie były dostępne - aby uzyskać pełną listę odpowiednich modułów, wyszukaj npm pracowników, pracowników sieci itp. Jeśli coś w szczególności działa lub nie działa, napisz komentarz.

Zaktualizuj 6

Od stycznia 2017 r . Jest mało prawdopodobne, że pracownicy sieci Web zostaną scaleni z Node.js.

Żądanie ściągnięcia nr 2133 pracowników: początkowa implementacja Petki Antonova od 8 lipca 2015 r. Została ostatecznie zamknięta przez Bena Noordhuisa 11 grudnia 2016 r., Który skomentował, że „obsługa wielu wątków dodaje zbyt wiele nowych trybów awarii, aby nie zapewniać wystarczających korzyści” oraz „my może to również osiągnąć przy użyciu bardziej tradycyjnych środków, takich jak pamięć współdzielona i wydajniejsza serializacja ”.

Aby uzyskać więcej informacji, zobacz komentarze do PR 2133 na GitHub.

Jeszcze raz dziękuję Matheusowi Moreira za wskazanie tego w komentarzach.

Zaktualizuj 6

Z przyjemnością informuję, że kilka dni temu, w czerwcu 2018 roku, pracownicy sieci Web pojawili się w Node 10.5.0 jako funkcja eksperymentalna aktywowana --experimental-workerflagą.

Aby uzyskać więcej informacji, zobacz:

🎉🎉🎉 Wreszcie! Mogę dokonać siódmej aktualizacji mojej 3-letniej odpowiedzi Stack Overflow, w której twierdzę, że tworzenie wątków a la Web Workers nie jest sprzeczne z filozofią Node, tylko tym razem mówiąc, że w końcu ją dostaliśmy! 😜👍

rsp
źródło
1
@NiCkNewman Thanks. Widzę, że pierwotne żądanie ściągnięcia w io.js jest teraz zamknięte i zastąpione innym - po dyskusji w komentarzach żądań ściągnięcia na GitHubie, być może uda ci się tam znaleźć jakieś informacje. Zobacz: Aktualizacja 2 w mojej odpowiedzi.
rsp
1
Tak, wygląda na to, że właśnie naprawili ostatni problem z libuv. Zastanawiam się, kiedy zdobędę moduł. Nie mogę się doczekać! Dzięki za informowanie nas na bieżąco ~ Edycja: właśnie się zainicjowałem: github.com/petkaantonov/io.js/commit/ ... No już, nadchodzi!
NiCk Newman,
1
Tak, to jest na żywo. (Jeszcze nie zaimplementowane), ale możesz pobrać źródło tutaj: github.com/petkaantonov/io.js/tree/ ... i skompilować, jeśli chcesz je przetestować! Robię to teraz ~
NiCk Newman
1
@NiCkNewman Dzięki za nowe informacje - dodałem je do odpowiedzi.
rsp
1
Czy możesz nas powiadomić o stanie workerswdrożenia Node.js ? Najnowsze komentarze w PR nr 2133 pochodzą z lutego; twórcy najwyraźniej napotkali problem i nie ma komentarzy wskazujących, że został on rozwiązany.
Matheus Moreira
8

Pochodzę ze starej szkoły myślenia, w której używaliśmy wielowątkowości do szybkiego tworzenia oprogramowania. Od 3 lat używam Node.js i jestem jego wielkim zwolennikiem. Jak wyjaśnił szczegółowo hasanyasin, jak działa węzeł i koncepcję asynchronicznej funkcjonalności. Ale pozwólcie, że dodam tutaj kilka rzeczy.

W dawnych czasach z pojedynczymi rdzeniami i niższymi częstotliwościami zegara próbowaliśmy różnych sposobów, aby oprogramowanie działało szybko i równolegle. w dniach DOS używamy do uruchamiania jednego programu na raz. Następnie w systemie Windows zaczęliśmy jednocześnie uruchamiać wiele aplikacji (procesów). Pojęcia takie jak zapobiegawcze i nie wywłaszczające (lub kooperatywne) były testowane. teraz wiemy, że zapobieganie było odpowiedzią na lepsze zadanie wieloprocesorowe na komputerach jednordzeniowych. Wraz z pojawieniem się koncepcji procesów / zadań i przełączania kontekstów. Niż koncepcja wątku, aby jeszcze bardziej zmniejszyć obciążenie przełączania kontekstu procesu. Wątek został ukuty jako lekka alternatywa dla tworzenia nowych procesów.

Tak więc, czy ci się to podoba, czy nie, wątek sygnałowy lub nie wielordzeniowy lub jednordzeniowy, twoje procesy zostaną wywłaszczone i podzielone na czas przez system operacyjny.

Nodejs to pojedynczy proces i zapewnia mechanizm asynchroniczny. Tutaj zadania są wysyłane do leżącego systemu operacyjnego w celu wykonania zadań, podczas gdy my czekamy w pętli zdarzeń na zakończenie zadania. Gdy otrzymamy zielony sygnał z systemu operacyjnego, wykonujemy wszystko, co musimy zrobić. W pewnym sensie jest to wielozadaniowość kooperacyjna / nie wywłaszczająca, więc nigdy nie powinniśmy blokować pętli zdarzeń przez bardzo długi okres czasu, w przeciwnym razie bardzo szybko zdegradujemy naszą aplikację.
Więc jeśli kiedykolwiek pojawi się zadanie, które blokuje naturę lub jest bardzo czasochłonne, będziemy musieli skierować je do prewencyjnego świata systemu operacyjnego i wątków. dobre przykłady tego można znaleźć w dokumentacji libuv . Również, jeśli chcesz zapoznać się z dokumentacją dalej można zauważyć, że FileI / O jest obsługiwana w wątkach w node.js .

Więc przede wszystkim chodzi o projektowanie naszego oprogramowania. Po drugie, zmiana kontekstu ma miejsce zawsze, bez względu na to, co ci powiedzą. Wątki istnieją i nadal istnieją z jakiegoś powodu, powodem jest to, że szybciej przełączają się między procesami.

Pod maską w node.js jest całe c ++ i wątki. Węzeł zapewnia sposób C ++ na rozszerzenie swojej funkcjonalności i dalsze przyspieszenie poprzez użycie wątków tam, gdzie są one niezbędne, tj. Blokowanie zadań, takich jak odczyt ze źródła, zapis do źródła, analiza dużych danych i tak dalej.

Wiem, że odpowiedź hasanyasin jest akceptowana, ale dla mnie wątki będą istnieć bez względu na to, co powiesz lub jak ukryjesz je za skryptami, po drugie, nikt nie rozbija rzeczy tylko dla szybkości, dzieje się to głównie w celu blokowania zadań. A wątki znajdują się w kręgosłupie Node.js, więc zanim całkowite rozbicie wielowątkowości jest prawidłowe. Również wątki różnią się od procesów, a ograniczenie związane z posiadaniem procesów węzłów na rdzeń nie dotyczy dokładnie liczby wątków, wątki są jak pod-zadania procesu. w rzeczywistości wątki wygrały; t nie pojawiają się w menedżerze zadań systemu Windows lub w górnej komendzie Linuksa. po raz kolejny mają mniejszą wagę niż procesy

limplash
źródło
Kod asynchroniczny nie jest wielką innowacją (w rzeczywistości mamy go od dziesięcioleci), a wielowątkowość nie jest jakąś przestarzałą technologią, którą należy zastąpić. Są to różne narzędzia z różnymi kompromisami, aw rzeczywistości można je nawet całkiem dobrze połączyć. Za każdym razem, gdy uruchamiasz węzeł-klaster, w rzeczywistości uruchamiasz wiele „wątków” (w tym przypadku procesów, ale to samo można osiągnąć z wątkami i być jeszcze bardziej lekkim). Albo weźmy Erlang lub przejść, które można uruchomić tysiące zielonych nici ...
Hejazzman
Myślę, że główną kwestią, której nam brakuje, jest to, że proces w systemie operacyjnym zawsze będzie odbywał się w sposób zapobiegawczy, aby zapewnić sprawiedliwość. Również w przypadku wielu procesorów możesz mieć rzeczywiste równoległe wykonywanie kodu, ale nawet wtedy będziesz mieć wywłaszczanie. Praca asynchroniczna jest również wykonywana przez system operacyjny w niektórych procesach.
limplash
4

Nie jestem pewien, czy w tym przypadku pracownicy sieciowi są istotni, są technikami po stronie klienta (działają w przeglądarce), podczas gdy node.js działa na serwerze. Włókna, o ile rozumiem, też się blokują, tj. Są dobrowolnymi wielozadaniowościami, więc możesz ich używać, ale powinieneś samodzielnie zarządzać przełącznikami kontekstu yield. Wątki mogą być właściwie tym, czego potrzebujesz, ale nie wiem, jak dojrzałe są w node.js.

lanzz
źródło
3
tylko dla twojej informacji, webworkers zostali (częściowo) przystosowani na node.js. I są dostępne jakonode-workers pakiecie. Spójrz na to: github.com/cramforce/node-worker
Parth Thakkar
Dobrze wiedzieć, dzięki. Dokumentów jest jednak bardzo mało, nie mam pojęcia, czy działa w osobnym wątku, procesie, czy po prostu działa w tym samym procesie i nie mam czasu, aby zagłębiać się w kod, więc nie mam pojęcia, czy będzie pracować dla twojego przypadku.
lanzz
@ParthThakkar: Ten projekt nie był poruszany od 3 lat (2 kiedy opublikowałeś) i nie przekroczył wersji 0.0.1.
mpen
@Mark: Powodem mojej niewiedzy jest to, że nie jestem jeszcze zawodowym programistą. Heck, nie jestem nawet na uniwersytecie. Wciąż jestem licealistą, który ciągle czyta o programowaniu - oprócz kierowania pracą szkoły. Nie jest więc możliwe, żebym miał wiedzę o wszystkich takich kwestiach. Właśnie opublikowałem to, co wiedziałem ...
Parth Thakkar
@Mark: Chociaż miło było z Twojej strony, że zwróciłaś uwagę na historię projektu. Takie rzeczy zostaną omówione w moich przyszłych odpowiedziach !! :)
Parth Thakkar
3

worker_threadszostał wdrożony i wysłany za flagą w [email protected]. To wciąż początkowa implementacja i potrzeba więcej wysiłków, aby uczynić ją bardziej wydajną w przyszłych wersjach. Warto spróbować najpóźniej node.

motss
źródło
2

W opinii wielu deweloperów Node jedną z najlepszych części Node jest w rzeczywistości jego jednowątkowa natura. Wątki wprowadzają całą masę problemów ze współdzielonymi zasobami, których Node całkowicie unika, robiąc tylko nieblokujące operacje we / wy.

Nie oznacza to, że Node jest ograniczony do jednego wątku. Po prostu metoda uzyskiwania współbieżności wątkowej różni się od tego, czego szukasz. Standardowym sposobem radzenia sobie z wątkami jest klaster moduł , który jest standardowo dostarczany z samym Node. Jest to prostsze podejście do wątków niż ręczne zajmowanie się nimi w kodzie.

Aby radzić sobie z programowaniem asynchronicznym w kodzie (jak w przypadku unikania zagnieżdżonych piramid wywołań zwrotnych), komponent [Future] w bibliotece Fibers jest przyzwoitym wyborem. Sugerowałbym również wypróbowanie Asyncblock, który jest oparty na Fibers. Włókna są fajne, ponieważ pozwalają na ukrycie wywołania zwrotnego przez duplikowanie stosu, a następnie przeskakiwanie między stosami na jednym wątku, gdy są potrzebne. Oszczędza kłopotów z prawdziwymi wątkami, zapewniając jednocześnie korzyści. Wadą jest to, że ślady stosu mogą stać się nieco dziwne podczas korzystania z włókien, ale nie są takie złe.

Jeśli nie musisz martwić się o rzeczy asynchroniczne i jesteś bardziej zainteresowany wykonywaniem dużej ilości przetwarzania bez blokowania, wystarczy proste wywołanie process.nextTick (wywołanie zwrotne) raz na jakiś czas.

genericdave
źródło
cóż, twoja sugestia - dotycząca klastrów - była tym, o czym początkowo myślałem. Ale problemem jest ich narzut - nowa instancja v8 musi być inicjowana za każdym razem, gdy nowy proces jest rozwidlony (~ 30 ms, 10 MB). Nie możesz więc stworzyć ich wielu. Jest to pobierane bezpośrednio z dokumentacji węzła: Te węzły potomne (dotyczące procesów potomnych) są nadal zupełnie nowymi instancjami V8. Przyjmij co najmniej 30 ms uruchamiania i 10 MB pamięci dla każdego nowego węzła. Oznacza to, że nie możesz stworzyć ich wielu tysięcy.
Parth Thakkar
1
To jest dokładnie idea klastra. Uruchamiasz jednego pracownika na rdzeń procesora. Więcej jest prawdopodobnie niepotrzebne. Nawet zadania wymagające dużej mocy obliczeniowej będą działać dobrze w stylu asynchronicznym. Jeśli jednak naprawdę potrzebujesz pełnowymiarowych wątków, prawdopodobnie powinieneś rozważyć całkowite przejście na inny serwer.
genericdave
1

Może trochę więcej informacji na temat zadań, które wykonujesz, pomogłoby. Dlaczego miałbyś (jak wspomniałeś w komentarzu do odpowiedzi genericdave) tworzyć ich wiele tysięcy? Typowym sposobem wykonywania tego typu czynności w Node jest uruchomienie procesu roboczego (za pomocą forka lub innej metody), który zawsze działa i może być przekazywany za pomocą komunikatów. Innymi słowy, nie uruchamiaj nowego pracownika za każdym razem, gdy musisz wykonać dowolne zadanie, które wykonujesz, ale po prostu wyślij wiadomość do już pracującego pracownika i uzyskaj odpowiedź, gdy zostanie wykonana. Szczerze mówiąc, nie widzę, aby powstało wiele tysięcy rzeczywistych wątków byłoby bardzo wydajne, nadal jesteś ograniczony przez swoje procesory.

Teraz, po tym wszystkim, wykonałem ostatnio dużo pracy z Hook.io, który wydaje się działać bardzo dobrze w tego rodzaju przenoszeniu zadań na inne procesy, może może osiągnąć to, czego potrzebujesz.

kbjr
źródło