node.js - 在单独的线程 Node Js 中运行长时间运行的快速 API 进程

标签 node.js multithreading express queue

我有一个 API 调用大约需要 5-10 分钟来处理。我围绕它设置了一个超时方法,以便立即获得状态为已排队的 API 响应。

下面是简单的视觉效果

doWork(object) => { /*... Takes 5 minutes */ }

app.post('/longProcess',(req,res)=> {
    setTimeout(this.doWork(req.body), 1000);
    res.send({ status: 'queued' });
})

这适用于第一个立即响应的请求。但是第二个请求被锁定等待 doWork 完成。

我真正想做的不是使用 SetTimeout,而是将 longProcess 发送到一个单独的单线程,一个一个地排队和处理论文。

有什么建议吗?

最佳答案

问题

问题不在于 doWork() 花费了很多时间,而在于它显然会在整个生命周期内阻塞您的线程,并且不会让事件循环有任何运行的机会。

可能的原因

这可能是由多种原因引起的,我在这里只能猜测,因为您没有显示 doWork() 的来源,甚至没有描述它的作用和方式。例如:

  • 您的 doWork() 可能会使用诸如 fs.readFileSync() 之类的阻塞操作或名称中带有 Sync 的其他函数。
  • 您的 doWork() 可能有一个 forwhile 循环,它会旋转 5-10 分钟并在这样做时阻塞事件循环.
  • 您的代码进行了一些严肃的数字运算,没有分成多个步骤让事件循环在这些步骤之间滚动。

一般来说,如果您的 doWork() 不阻塞您的主线程,并且它不应该阻止其他连接获得服务,即使是一毫秒,它也可能需要数小时才能运行。

解决方案

停止阻塞线程

该问题最简单的解决方案可能是避免阻塞函数调用(那些带有 Sync 后缀或您自己的函数)、长时间运行的循环和没有分成短步骤的繁重计算。

例如:

  • 不要使用 readFileSync(),而是使用 readFile()
  • 不要使用长时间运行的 for/while 循环,而是使用 process.nextTick()
  • 不要使用非常深的递归(可能要归功于 TCO),而是使用通过 process.nextTick()
  • 分成多个部分的循环

如果无法应用上述解决方案(由于我对您的 doWork() 函数一无所知,所以我无从得知)那么您可以采取另一种方法。您还可以做一些其他事情。

产生一个进程

另一种解决方案是在每次启动长时间运行的任务时使用 child_process 生成不同的进程。当 child 结束工作并做出相应 react 时,您的主要流程可能会收到通知,但在等待时不会被阻止。请参阅:https://nodejs.org/api/child_process.html

使用队列

您还可以使用待处理作业队列并由其他进程处理它们,而不会影响您的主程序,该程序只会安排新任务而不执行或等待它们。通常像这样的队列是用 Redis 完成的,但也可以用 CouchDB 或 MongoDB 完成。您需要有一些挂起任务的中央注册表,您的工作进程可以从中获取它们。在 Node 中有很多模块可以做到这一点,例如:

请参阅这些模块的文档以了解哪一个最适合您的需求。

关于node.js - 在单独的线程 Node Js 中运行长时间运行的快速 API 进程,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40085654/

相关文章:

mysql - 序列化 uuid 的外键给出错误 1215

node.js - 在 NodeJS 中运行 Postman Newman 时通过测试修改环境

c# - 如何在特定核心上启动线程?

node.js - Passportjs 用户对象不返回密码以进行比较密码

javascript - 如何使用 AngularJS 上传文件并使用 ExpressJS 保存?

node.js - 如何在 Node.js 中编写同步函数

node.js - 如何在 Node Js 中使用和发布来自 Amazon MQ 的消息?

node.js - 使用多方流调整图像大小

c# - 如何修复捕获TimeoutException?

java - 简单的多线程程序崩溃?