Procesy w tle w Node.js.

99

Jakie jest dobre podejście do obsługi procesów w tle w aplikacji NodeJS?

Scenariusz : Po tym, jak użytkownik opublikuje coś w aplikacji, chcę skompresować dane, zażądać dodatkowych danych z zasobów zewnętrznych itp. Wszystko to jest dość czasochłonne, więc chcę, aby było to poza pętlą req / res. Idealnie byłoby po prostu mieć kolejkę zadań, w której można szybko zrzucić zadanie, a demon lub program uruchamiający zadania zawsze pobierze najstarsze z nich i przetworzy je.

W RoR zrobiłbym to z czymś w rodzaju Delayed Job. Jaki jest odpowiednik tego interfejsu API dla węzła?

Ole Spaarmann
źródło
4
Pytanie jest zaleceniem dotyczącym oprogramowania, tak jak jest teraz sformułowane, co w końcu zostanie zamknięte. Gdybyś zamienił ostatnie zdanie na „Jaki jest odpowiednik tego interfejsu API w NodeJS?” staje się bardziej na temat. Chciałbym, aby ta odpowiedź została zakończona, a nie zamknięta, ponieważ muszę zrobić coś podobnego.
ssube
Dzięki, przeformułowałem to.
Ole Spaarmann
2
Dobre sugestie poniżej. Jest też ChildProcessAPI, które może być przydatne. nodejs.org/api/child_process.html
lispHK01
stackoverflow.com/users/69349/ole-spaarmann - chciałbym wiedzieć, co ostatecznie wybrałeś i gdybyś mógł podać bardzo prosty przykład tego, jak zintegrowałeś swoją decyzję z NodeJS - dzięki!
MLissCetrus
@MLissCetrus Zdecydowałem się nauczyć Elixir i nie używać już NodeJS :)
Ole Spaarmann

Odpowiedzi:

114

Jeśli chcesz czegoś lekkiego, działającego w tym samym procesie co serwer, bardzo polecam Bull . Posiada proste API, które pozwala na precyzyjną kontrolę nad kolejkami.

Jeśli szukasz czegoś, co działa jako samodzielny proces roboczy, może zajrzyj do Kue . Może działać jako serwer RESTful API, a nawet ma napisane dla niego kilka aplikacji front-end.

Jeśli znasz Resque Rubiego, istnieje implementacja węzła o nazwie Node-resque

Bull, Kue i Node-resque są wspierane przez Redis , który jest wszechobecny wśród kolejek roboczych Node.js. Wszyscy 3 byliby w stanie zrobić to, co robi RoR's DelayedJob, to kwestia określonych funkcji, które chcesz, i preferencji API.

Yuri Zarubin
źródło
3
To bardzo dobra odpowiedź, ale wspomnienie o ChildProcess API i module webworker-thread może sprawić, że będzie świetnie. ;)
ssube
@ssube Nie zgadzam się z tobą. Chyba że masz na myśli tworzenie rozwidlenia, które patrzy na kolejkę do wykonania jakiegoś polecenia, masz rację. +1 ode mnie. Child_process jest tym, czego używam, a moim problemem jest to, że mógłbym otworzyć ogromny zestaw procesów, ale gdybym miał sposób zarządzać zadaniami do uruchomienia w kolejce, byłbym szczęśliwy, że CP jest dobrym rozwiązaniem. Można to zrobić, ale chodzi o to, aby nie wykonywać całej pracy samodzielnie, ale aby ponownie wykorzystać kod, który został przetestowany w walce (w tym przypadku coś takiego jak Kue, które wykonuje całą potrzebną magię i umożliwia integracje API).
dewwwald
Czy Bull działa z klastrowaniem PM2? A może musisz ręcznie tworzyć własne klastry, jak pokazano w ich dokumentacji?
Shayan Nahrvar
33

Zadania w tle nie są bezpośrednio związane z usługami internetowymi, więc nie powinny być w tym samym procesie. W miarę skalowania w górę użycie pamięci przez zadania w tle wpłynie na wydajność usługi sieci Web. Ale jeśli chcesz, możesz umieścić je w tym samym repozytorium kodu, cokolwiek ma większy sens.

Dobrym wyborem do przesyłania wiadomości między dwoma procesami byłoby redis , jeśli upuszczanie wiadomości od czasu do czasu jest w porządku. Jeśli chcesz, aby żadna wiadomość nie została pozostawiona, będziesz potrzebować bardziej ciężkiego brokera, takiego jak Rabbit . Twój proces usługi sieciowej może publikować, a proces pracy w tle może subskrybować.

Nie jest konieczne, aby te dwa procesy były współhostowane, mogą znajdować się na oddzielnych maszynach wirtualnych, kontenerach Docker, niezależnie od tego, z czego korzystasz. Pozwala to na skalowanie bez większych problemów.

jagoda
źródło
4
Naprawdę jedyna odpowiedź, która wspomniała o Króliku? Oto odpowiedź przedsiębiorstwa. +1
Augie Gardner
@wberry Czy Twoja odpowiedź zmieniłaby się, biorąc pod uwagę wątki pracowników Nodejs?
Brendan
Nie pracowałem z Node od kilku lat. Ale ten nowy system wątków wydaje się sprzeczny z pierwotnym zamysłem języka. Moim instynktem jest unikanie używania tego modułu z wyjątkiem tych wąskich przypadków, do których był przeznaczony - obliczenia intensywnie korzystające z procesora, które są niewygodne do wykonania z setImmediatewywołaniami.
jagoda
Głównymi problemami związanymi z łączeniem kodu porządkowego i transakcyjnego w tym samym procesie są pamięć i operacje we / wy. Jeśli kod porządkowy zamieni się w wieprz, może to wpłynąć na ruch. Korzystanie z pakietu Worker wyeliminowałoby potrzebę pośrednika, ale naraziłoby Cię na takie ryzyko.
jagoda
11

Jeśli korzystasz z MongoDB, polecam Agendę . W ten sposób oddzielne wystąpienia Redis nie są uruchomione, a funkcje, takie jak planowanie, kolejkowanie i interfejs sieciowy, są obecne. Interfejs Agendy jest opcjonalny i można go oczywiście uruchomić oddzielnie.

Poleciłbym również ustawienie luźno powiązanej abstrakcji między logiką aplikacji a systemem kolejkowania / planowania, aby w razie potrzeby można było wymienić cały system przetwarzania w tle. Innymi słowy, trzymaj jak najwięcej logiki aplikacji / przetwarzania z dala od definicji zadań w agendzie, aby były lekkie.

sean2078
źródło
3

Chciałbym zasugerować użycie Redis do planowania zadań. Ma wiele różnych struktur danych, zawsze możesz wybrać taką, która lepiej pasuje do twojego przypadku użycia.

Wspomniałeś o RoR i DJ, więc zakładam, że znasz sidekiq. Możesz użyć node-sidekiq do planowania zadań, jeśli chcesz, ale jego nieoptymalne imo, ponieważ jego głównym celem jest integracja nodejs z RoR.

Do demonizacji pracownika polecam używanie PM2 . Jest szeroko stosowany i aktywnie utrzymywany. Rozwiązuje wiele problemów (np. Wdrażanie, monitorowanie, tworzenie klastrów), więc upewnij się, że nie będzie to dla Ciebie przesada.

Stefkin
źródło
1

Spróbowałem bee-queue & bull i ostatecznie wybrałem byka. Najpierw wybrałem kolejkę pszczół b / c jest to dość proste, ich przykłady są łatwe do zrozumienia, podczas gdy przykłady byków są nieco skomplikowane. Bee's wiki Bee Queue's Origin również współgra ze mną. Ale problem z pszczołami polega na tym, że <1> ich czas rozwiązywania problemów jest dość długi, ich ostatnia aktualizacja miała miejsce 10 miesięcy temu. <2> Nie mogę znaleźć łatwego sposobu na wstrzymanie / anulowanie pracy.

Z drugiej strony Bull często aktualizuje swoje kody, reagując na problemy. Ocena kolejki zadań Node.js mówi, że słabością byka jest „długi czas rozwiązywania problemów”, ale moje doświadczenie jest odwrotne!

Ale w każdym razie ich interfejs API jest podobny, więc przełączanie się między nimi jest dość łatwe.

Qiulang
źródło
-7

Proponuję użyć odpowiedniego frameworka Node.js do zbudowania aplikacji.

Myślę, że najpotężniejszym i najłatwiejszym w użyciu jest Sails.js .

Jest to framework MVC, więc jeśli jesteś przyzwyczajony do programowania w ROR, okaże się to bardzo łatwe!

Jeśli go używasz, jest już potężnym (w terminach javascript) menedżerem zadań.

new sails.cronJobs('0 01 01 * * 0', function () {
   sails.log.warn("START ListJob");
}, null, true, "Europe/Dublin");

Jeśli potrzebujesz więcej informacji, nie wahaj się ze mną skontaktować!

Zio Mak Sò
źródło
6
Szukam menedżera procesów w tle dla Node. Z definicji powinno to być oddzielone od Twojej aplikacji internetowej. I nie powinno mieć znaczenia, czy używasz Sails, Express, Hapi czy czegokolwiek lubisz.
Ole Spaarmann
Ok, możesz spróbować Bull lub Webworker-Threads ... powodzenia z Node.js :)
Zio Mak Sò
Wygląda na to, że sails.js jest dość duży i robi znacznie więcej niż cronJobs. Znalazłem node-cron ( github.com/kelektiv/node-cron ), z którego na pewno korzysta sails.js.
pbatey