问题:如何在 Node JS 中执行/中止长时间运行的任务?

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

我们希望将其作为后台任务运行。如果用户决定更改参数并重新构建它,我们需要能够启动报表构建过程、监控它并中止它。

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

1)以异步方法启动构建,并返回给用户,socket.io报告进度?

  1. 为构建脚本分离一个子进程?

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

通过我研究过的几种方法,我陷入了相同的两个领域;

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

任何指针将不胜感激......

解答

最好的办法是将此任务与您的主应用程序分开。也就是说,在后台运行它很容易。要在后台运行它并在没有消息队列等的情况下进行监控,最简单的方法是child_process

1.您可以在用户调用的端点(或url)上启动spawn作业。

2.接下来设置一个socket返回子进程的实时监控

  1. 添加另一个端点以停止作业,由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() }
})

要监控子进程,您可以使用pidusage,例如我们在PM2中使用它。添加一条路线来监控作业并每秒调用一次。工作结束时不要忘记释放内存。


您可能想查看这个库,它将帮助您管理跨微服务的多处理。

Logo

MongoDB社区为您提供最前沿的新闻资讯和知识内容

更多推荐