Proces potomny node.js - różnica między spawn i fork

141

To może wydawać się podstawowym pytaniem, ale nie mogłem znaleźć żadnej dokumentacji:

Jaka jest różnica między rozwidlaniem i spawningiem procesu node.js? Czytałem, że rozwidlenie jest szczególnym przypadkiem tarła, ale jakie są różne przypadki użycia / rekurencje dla każdego z nich?

Hitesh
źródło

Odpowiedzi:

215

Spawn to polecenie przeznaczone do uruchamiania poleceń systemowych. Po uruchomieniu spawn wysyłasz mu polecenie systemowe, które zostanie uruchomione we własnym procesie, ale nie będzie wykonywać żadnego dalszego kodu w procesie węzła. Możesz dodać detektory dla procesu, który utworzyłeś, aby umożliwić interakcję kodu z zwołanym procesem, ale nie zostanie utworzona żadna nowa instancja V8 (chyba że twoja komenda jest kolejną komendą węzła, ale w tym przypadku powinieneś użyć fork!) I tylko jedna kopia modułu węzła jest aktywna na procesorze.

Fork to specjalna instancja spawn, która uruchamia nową instancję silnika V8. Oznacza to, że zasadniczo można utworzyć wielu pracowników działających na tej samej bazie kodu węzła lub być może na innym module do określonego zadania. Jest to najbardziej przydatne do tworzenia puli pracowników. Chociaż model zdarzeń asynchronicznych węzła umożliwia dość wydajne wykorzystanie pojedynczego rdzenia maszyny, nie pozwala procesowi węzła na korzystanie z maszyn wielordzeniowych. Najłatwiejszym sposobem osiągnięcia tego jest uruchomienie wielu kopii tego samego programu na jednym procesorze.

Dobrą zasadą jest jeden do dwóch procesów węzłowych na rdzeń, być może więcej w przypadku maszyn z dobrym współczynnikiem zegara pamięci RAM / procesora lub w przypadku procesów węzłowych obciążonych we / wy i niewielkim obciążeniem procesora, aby zminimalizować czas przestoju zdarzenia pętla czeka na nowe zdarzenia. Jednak ta ostatnia sugestia jest mikrooptymalizacją i wymagałaby starannej analizy porównawczej, aby upewnić się, że Twoja sytuacja odpowiada potrzebom wielu procesów / rdzenia. W rzeczywistości możesz zmniejszyć wydajność, tworząc zbyt wielu pracowników dla swojej maszyny / scenariusza.

Ostatecznie możesz użyć spawn w sposób, który zrobił to powyżej, wysyłając spawn polecenie Node. Ale to byłoby głupie, ponieważ fork robi pewne rzeczy, aby zoptymalizować proces tworzenia instancji V8. Po prostu wyjaśniam, że ostatecznie spawn obejmuje widelec. Widelec jest optymalny dla tego konkretnego i bardzo użytecznego przypadku użycia.

http://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback

ChrisCM
źródło
@ChrisCM, jeśli użyję, powiedzmy, var child = require('child_process').fork('child.js');na przykład w mojej głównej aplikacji, będę miał teraz uruchomione 2 oddzielne rdzenie. Gdybym uruchomić ciężki dla pętli w child.js (procesu), bym zasadniczo być wykorzystanie więcej rdzeni do child.js mocy, prawda? Czy to użycie procesora wpłynęłoby jednak na mój główny rdzeń aplikacji?
NiCk Newman
2
Nie można nic zrobić na procesorze bez wpływu na inne rzeczy. Planowanie, wykorzystanie współdzielonej pamięci podręcznej, ruch na magistrali itp. Powinien jednak korzystać z oddzielnego rdzenia i pozostawić główną pętlę uruchamiania NAJBARDZIEJ nienaruszoną. Tak jak w przypadku, nie są to poważne negatywne skutki, których można się spodziewać po dwóch procesach działających na tym samym jednordzeniowym procesorze. W tym momencie prawidłowa optymalizacja zależy od systemu operacyjnego i konfiguracji sprzętu. Różne konfiguracje mogą dawać różne wyniki.
ChrisCM
@ChrisCM Tak, używam globalnego MonsterLoop do synchronizowania pozycji potworów, a obiekt, który iteruje, może mieć nawet 5000 kluczy. Iteruję to co 2 sekundy i rozwidlenie wygląda na to, że niszczy setki zużycia pamięci z mojego procesora (główna gra). Wolałbym to zrobić w ten sposób, zamiast grupować tę pętlę i sprawić, by działała xx razy na rdzeń, co miałem ... Ty do wglądu ~ Teraz po prostu nie wiem, czy powinienem używać Redis, czy wewnętrznego IPC: P
NiCk Newman
2
Dziękuję za odpowiedź „dlaczego” - wszystkie posty, które przeczytałem, aż w tym jednym przegapiłem tę prostą część wyjaśnienia.
aaaaaa
@ChrisCM W tobie odpowiadasz "..ale nie wykonuje żadnego dalszego kodu w procesie twojego węzła ..". Czy to oznacza, że ​​główny wątek czeka i nic nie przetwarza… Jeśli TAK, to jaki jest pożytek z używania spawn tutaj ..?
Abhi
9

TLDR

Spawn

Kiedy tworzony jest spawn - tworzy interfejs przesyłania strumieniowego między procesem nadrzędnym i podrzędnym.

interfejs strumieniowy oznacza - buforowanie danych w formacie binarnym w formacieONE TIME

Fork

Kiedy tworzony jest fork - tworzy kanał komunikacji między procesem nadrzędnym i podrzędnym

środki komunikacji - powiadamianie

Difference

Cóż, oba wyglądają na ten sam transfer danych , z wyjątkiem poniższej różnicy

spawn będzie przydatny, gdy chcesz zrobić ciągły bufor danych w formacie binarnym / kodowania , Np. - Przenieś plik wideo 1 GB, obraz, pliki dziennika wONE TIME

fork będzie przydatny, gdy chcesz na przykład wysyłać wiadomości - JSONlub XMLprzesyłać dane

Conslusion

spawn powinien być używany do przesyłania strumieniowego dużych zbiorów danych / plików / obrazów Z procesu spawn DO procesu nadrzędnego

fork powinien być używany do obsługi komunikatów Json / Xml.

  • Załóżmy na przykład, że z rodzica utworzono 10 procesów fork.
  • a każdy proces wykonuje jakąś operację
  • a każdy proces po zakończeniu operacji wyśle ​​wiadomość do rodzica: „ proces nr 4 zakończony ”, „ proces nr 8 zakończony
vijay
źródło
A co z ciągłym rejestrowaniem danych od rodzica do dziecka, a na końcu do pliku?
Esqarrouth
1
@Esqarrouth, musisz określić, czy będzie to ciągły strumień, czy wiadomości. I użyłeś słowa „ciągłe rejestrowanie”, myślę, że będziesz pisać do logów (JSON) dla dziecka. Jeśli tak, użyj FORKinnego, jeśli masz bardzo duży fragment danych do BUFOROWANIA, a następnie użyjSPAWN
vijay
5
  • spawn - child_process.spawn uruchamia nowy proces z podanym poleceniem.
  • fork - Metoda child_process.fork jest specjalnym przypadkiem metody spawn () do tworzenia procesów potomnych.

Metoda spawn ()

child_process.spawn uruchamia nowy proces z podanym poleceniem. Ma następujący podpis -

child_process.spawn(command[, args][, options])

Przeczytaj więcej o opcjach

Metoda spawn () zwraca strumienie (stdout & stderr) i powinna być używana, gdy proces zwraca objętość danych. spawn () zaczyna otrzymywać odpowiedź zaraz po rozpoczęciu wykonywania procesu.

Metoda fork ()

child_process.fork to specjalny przypadek funkcji spawn () do tworzenia procesów węzła. Ma następujący podpis -

 child_process.fork(modulePath[, args][, options])

Metoda fork zwraca obiekt z wbudowanym kanałem komunikacyjnym oprócz wszystkich metod w normalnej instancji ChildProcess.

Igor Litvinovich
źródło