如何执行/中止JS中的长时间运行的任务?

具有Mongo DB的NodeJS服务器 – 一个function将从DB生成报告JSON文件,这可能需要一段时间(60秒以上 – 必须处理数十万条logging)。

我们希望将其作为后台任务运行。 我们需要能够启动一个报表生成过程,监视它,并在用户决定更改参数并重新构build时终止它。

节点最简单的方法是什么? 不要真的想进入单独的工作服务器处理工作,消息队列等领域 – 我们需要保持在同一个盒子和相当简单的实现。

1)作为asynchronous方法启动构build,并返回给用户,与socket.io报告进度?

2)分离构build脚本的subprocess?

3)使用类似https://www.npmjs.com/package/webworker-threads ?

用我看过的几种方法,我就陷在了同样的两个方面。

1)如何监控进度? 2)如果用户重新提交数据,如何中止现有的构build过程?

任何指针将不胜感激…

最好的办法是把这个任务从你的主应用程序中分离出来。 也就是说,在后台运行它会很容易。 为了在后台运行而不用消息队列等等,最简单的方法就是使用child_process

  1. 您可以在用户调用的端点(或url)上启动一个spawn作业。
  2. 接下来,设置一个socket来返回subprocess的实时监控
  3. 添加另一个端点来停止作业,并返回一个唯一的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() } }) 

为了监视subprocess,你可以使用pidusage ,我们在PM2中使用它。 添加一个path来监控一个工作,并每秒钟调用一次。 工作结束时不要忘记释放内存。


你可能想看看这个库 ,这将帮助你pipe理微服务的多处理。

Interesting Posts