Node.js 如何在Node JS中执行/中止长时间运行的任务?
带有Mongo DB的NodeJS服务器—一个功能将从DB生成一个报告JSON文件,这可能需要一段时间(60秒以上—必须处理数十万个条目) 我们希望将其作为后台任务运行。我们需要能够启动报表生成过程,监视它,如果用户决定更改参数并重新生成它,则中止它 使用node最简单的方法是什么?我真的不想进入单独的工作服务器处理作业、消息队列等的领域——我们需要将其保持在同一个框中,并且实现相当简单 1) 以异步方法启动构建,并返回给用户,socket.io报告进度 2) 为构建脚本派生一个子进程 3) 使用类似的东西 在我所看到的几个方法中,我被困在相同的两个方面 1) 如何监控进度? 2) 如果用户重新提交数据,如何中止现有的生成过程Node.js 如何在Node JS中执行/中止长时间运行的任务?,node.js,multithreading,mongodb,child-process,long-running-processes,Node.js,Multithreading,Mongodb,Child Process,Long Running Processes,带有Mongo DB的NodeJS服务器—一个功能将从DB生成一个报告JSON文件,这可能需要一段时间(60秒以上—必须处理数十万个条目) 我们希望将其作为后台任务运行。我们需要能够启动报表生成过程,监视它,如果用户决定更改参数并重新生成它,则中止它 使用node最简单的方法是什么?我真的不想进入单独的工作服务器处理作业、消息队列等的领域——我们需要将其保持在同一个框中,并且实现相当简单 1) 以异步方法启动构建,并返回给用户,socket.io报告进度 2) 为构建脚本派生一个子进程 3) 使
非常感谢您提供任何提示…最好将此任务与主应用程序分开。也就是说,在后台运行它很容易。 要在后台和monit中运行它而不使用消息队列等,最简单的方法是使用
子进程
spawn
作业套接字
,以返回子进程的实时监视1返回的唯一id。
(或否,取决于您的并发需要)var spawn = require('child_process').spawn
var job = null //keeping the job in memory to kill it
app.get('/save', function(req, res) {
if(job && job.pid)
return res.status(500).send('Job is already running').end()
job = spawn('node', ['/path/to/save/job.js'],
{
detached: false, //if not detached and your main process dies, the child will be killed too
stdio: [process.stdin, process.stdout, process.stderr] //those can be file streams for logs or wathever
})
job.on('close', function(code) {
job = null
//send socket informations about the job ending
})
return res.status(201) //created
})
app.get('/stop', function(req, res) {
if(!job || !job.pid)
return res.status(404).end()
job.kill('SIGTERM')
//or process.kill(job.pid, 'SIGTERM')
job = null
return res.status(200).end()
})
app.get('/isAlive', function(req, res) {
try {
job.kill(0)
return res.status(200).end()
} catch(e) { return res.status(500).send(e).end() }
})
为了监视您可以使用的子进程,我们在中使用它。添加监视作业的路由,并每秒调用一次。作业结束时,不要忘记释放内存
您可能想了解一下,这将帮助您管理跨微服务的多处理。谢谢@soyuka的回答。使用
job
var-它保留对子对象的引用,因此您可以停止它-但是它在PID上工作吗?他们被重新利用了,不是吗?因此,我们生成的作业可能会完成,并且它的PID会被释放,以供任何其他新进程使用?这意味着job.kill()如果单独使用PID,可能会杀死另一个进程?或者它不是那样工作的……只要检查一下文档,它就会说。。。当信号无法传递时,可能会发出“错误”事件。向已退出的子进程发送信号不是错误,但可能会产生不可预见的后果:如果PID(进程ID)已被重新分配给另一个进程,信号将被传递给该进程。接下来会发生什么,大家都可以猜测但是根据您的exmaple,在完成时取消引用应该可以解决这个问题!!很抱歉,错过了。这段代码似乎一次只允许一个报告作业,如果试图启动第二个作业,它将覆盖(并失去对上一个作业的跟踪)。@jfriend00确实,这就是我谈到并发性需求的原因(问题中未说明)。如果您想要更多的作业,只需保留一个包含子进程的pid缓存阵列@MattBryson实际上,您必须确保在作业结束时删除内存引用(exit
或close
事件)<代码>关闭与捕获信号时的STD
和退出
相关。@jfriend00添加了一个条件,如果作业已经在运行。请记住,这是一个小草稿,我想给出一些关于如何做的提示,但我没有做一个完整的工作示例;)。