我如何避免阻止快递服务?

问题描述 投票:0回答:2

[在节点中使用Express制作REST服务时,如何防止阻止任务阻止整个rest服务?以以下特快专递服务为例:

const express = require('express');
const app = express();

app.get('/', (req, res) => res.send('Hello, World'));

const blockService = async function () {
    return new Promise((resolve, reject) => {
        const end = Date.now() + 20000;
        while (Date.now() < end) {
            const doSomethingHeavyInJavaScript = 1 + 2 + 3;
        }
        resolve('I am done');
    });
}

const blockController = function (req, res) {
    blockService().then((val) => {
        res.send(val);
    });
};

app.get('/block', blockController);

app.listen(3000, () => console.log('app listening on port 3000'));

在这种情况下,对/ block的调用将使整个服务在20秒钟内无法访问。如果有许多客户端在使用该服务,这将是一个大问题,因为在此期间,其他客户端将无法访问该服务。这显然是while循环阻塞代码并因此挂起主线程的问题。该代码可能令人困惑,因为尽管在blockService中使用了promise,主线程仍然挂起。如何确保blockService将运行工作线程而不是事件循环?

node.js express event-loop
2个回答
1
投票

默认情况下,node.js在单个线程中运行Javascript代码。因此,如果您在请求处理程序中确实有CPU密集型代码(如上所示),那确实是一个问题。您的选择如下:

  1. 启动工作线程并在工作线程中运行CPU密集型代码。从版本10开始,node.js为此已具有辅助线程。然后,您可以通过消息传递将结果传回主线程。

  2. 启动运行node.js代码或任何类型代码的任何其他进程,并在该其他进程中计算结果。然后,您可以通过消息传递将结果传回主线程。

  3. 使用节点集群来启动N个进程,以便一旦某个进程因CPU密集型操作而停滞,希望其他进程中的至少一个可以自由运行其他请求。

[请注意,服务器所做的许多事情,例如读取文件,进行网络连接,向数据库发出请求都是异步且无阻塞的,因此实际上拥有大量CPU密集型代码并不罕见。因此,如果这只是您自己的一个好奇的例子,那么在设计线程或集群之前,应确保服务器中确实存在CPU密集型问题。


0
投票

Node.js是使用单个运行时线程的基于事件的模型。由于您发现的原因,Node.js并不是CPU绑定任务(或同步阻止任务)的理想选择。 Node.js最适合异步协调I / O。

worker-threads在Node.js v12中发布。这使您可以使用另一个线程来阻止任务。它们相对简单易用,如果您绝对需要卸载阻止任务,则可以使用。

© www.soinside.com 2019 - 2024. All rights reserved.