Node.js 中的后台进程

131

如何处理NodeJS应用程序中的后台进程?

场景: 用户在应用程序中发布内容后,我想要对数据进行处理,从外部资源请求附加数据等操作。所有这些操作都需要花费大量时间,因此我希望将其放在req/res循环之外。理想情况下,只需具有作业队列即可快速转移作业,并且守护进程或任务运行程序将始终获取最旧的作业并进行处理。

在RoR中,我会使用类似于Delayed Job的工具来完成。在Node中,是否有与该API等效的工具?


7
该问题目前的措辞是软件推荐,因此最终会被关闭。如果您将最后一句替换为“What is the NodeJS equivalent of this API?”,它就会更符合主题。我希望看到这个问题得到答复,而不是被关闭,因为我需要做类似的事情。 - ssube
2
下面有很好的建议。还有可能会有用的ChildProcess API。https://nodejs.org/api/child_process.html - user2524973
https://stackoverflow.com/users/69349/ole-spaarmann - 我很想知道你最终选择了什么,并且如果你能提供一个非常简单的示例来展示如何将你的决定与 NodeJS 集成在一起,那就太感谢了! - MLissCetrus
1
@MLissCetrus 我选择学习Elixir而不再使用NodeJS :) - Ole Spaarmann
https://stackoverflow.com/users/69349/ole-spaarmann - 啊...更容易?更难?为什么? - MLissCetrus
显示剩余2条评论
6个回答

138

如果您需要轻量级的系统,可以在服务器进程中运行,我强烈推荐使用Bull。它具有简单的API,可以对队列进行精细的控制。

如果您熟悉Ruby的Resque,则有Node.js的实现称为Node-resque

Bull和Node-resque都由Redis支持,它在Node.js工作队列中非常普遍。它们能够做到RoR的DelayedJob所做的事情,这只是涉及到您需要的特定功能和API首选项。


3
这是一个非常好的答案,但如果提到ChildProcess API和webworker-threads模块会更棒。 ;) - ssube
@ssube 我不同意你的观点。除非你是指创建一个查看队列以运行某些命令的分支,否则你是正确的。我给你点赞。Child_process是我正在使用的,我的问题是我可以打开一组巨大的进程,但如果我有一种管理要在队列中运行的任务的方法,那么我会很高兴CP是一个好的解决方案。这是可以做到的,但重点是不要自己做所有的工作,而是重用经过实战检验的代码(在这种情况下,像Kue这样的东西可以做到你需要的所有魔法并允许API集成)。 - dewwwald
1
Bull能够与PM2集群一起工作吗?还是需要像他们的文档中所示手动创建自己的集群? - Shayan Nahrvar
@Yuri Zarubin,您的回答应该被编辑以提到Kue现在已经被弃用。 - Fed

42

后台作业与您的Web服务工作没有直接关系,因此它们不应该在同一个进程中。随着规模的扩大,后台作业的内存使用量将影响Web服务的性能。但是,如果您愿意,可以将它们放在同一个代码存储库中,无论哪种方法更合理。

两个进程之间进行消息传递的一个很好的选择是Redis,如果偶尔丢失一条消息没问题的话。如果你想保证“没有留下的消息”,你需要一个更重量级的代理,比如RabbitMQ。您的Web服务进程可以发布,后台作业进程可以订阅。

这两个进程不必共同托管,它们可以位于单独的VM、Docker容器或任何您使用的环境中。这使您能够轻松扩展而无需太多麻烦。


8
唯一提到兔子的答案就是这个了?这是企业级答案。+1 - Augie Gardner
@wberry 如果考虑到Nodejs工作线程,你的答案会改变吗? - Brendan
我已经有几年没有使用Node了。但是这个新的线程系统似乎违背了语言最初的意图。我的直觉是除非在那些本来就是为之设计的狭窄情况下(即使用setImmediate调用实现起来很麻烦的CPU密集型计算),否则应该避免使用这个模块。 - wberry
将清理代码和事务性代码合并到同一进程中的主要问题是内存和I/O。如果清理代码变得过于繁琐,它可能会影响流量。使用Worker包可以消除代理的需要,但会使您面临这些风险。 - wberry

14
如果您使用MongoDB,我推荐使用Agenda。这样,独立的Redis实例不会运行,并且调度、排队和Web UI等功能都存在。当然,Agenda UI是可选的,可以单独运行。
另外,建议在应用逻辑和队列/调度系统之间建立松散耦合的抽象层,以便在需要时可以完全替换整个后台处理系统。换句话说,尽量将应用程序/处理逻辑与Agenda作业定义分离,以使它们轻量化。

5
我建议使用Redis来进行作业调度,它拥有丰富的不同数据结构,您可以选择最适合您用例的一种。
您提到了RoR和DJ,所以我认为您熟悉sidekiq。如果您想要,您可以使用node-sidekiq进行作业调度,但在我看来,这种方法并不是最优的,因为它的主要目的是将nodejs与RoR集成。
对于工作程序的守护进程,我建议使用PM2。它被广泛使用,并得到积极维护。它解决了许多问题(例如部署、监控、集群),因此请确保它不会给您带来过多负担。

4
我尝试过bee-queuebull,最终选择了bull。一开始我选择bee-queue是因为它很简单,他们的示例很容易理解,而bull的示例有点复杂。bee-queue的wiki Bee Queue's Origin 也让我感同身受。但是bee存在两个问题:<1>他们的问题解决时间相当慢,最近的更新是10个月前。<2>我找不到一个简单的方法来暂停/取消任务。
另一方面,Bull经常更新他们的代码,并回应问题。Node.js job queue evaluation说bull的弱点是“慢问题解决时间”,但我的经验与此相反!
但无论如何,它们的API类似,所以从一个切换到另一个相当容易。

-8

我建议使用一个合适的Node.js框架来构建您的应用程序。

我认为最强大且易于使用的是Sails.js

它是一个MVC框架,所以如果您习惯于在ROR中开发,您会发现它非常容易!

如果您使用它,它已经提供了一个强大(在JavaScript术语中)的作业管理器。

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

如果您需要更多信息,请随时与我联系!


6
我正在寻找一款Node的后台进程管理器。根据定义,这应该是与您的Web应用程序分开的。而且无论您使用Sails、Express、Hapi或其他任何喜欢的框架都不应该有问题。 - Ole Spaarmann
好的,你可以尝试使用Bull或Webworker-Threads...祝你在Node.js中好运 :) - Zio Mak Sò
看起来sails.js相当强大,不仅仅是cronJobs。我发现node-cron(https://github.com/kelektiv/node-cron)应该就是sails.js使用的东西。 - pbatey
为什么在Node.js或JS中的每个人都建议使用包,没有人使用原生JS吗? - supa pati

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接