在繁重的工作量下如何使Node.JS表示回复请求?

时间:2018-09-27 01:13:52

标签: javascript node.js express

我正在创建一个nodejs Web处理器。我的处理时间大约需要1分钟。我POST到服务器并使用GET

来获取状态

这是我的简化代码

// Configure Express
const app = express();
app.listen(8080);

// Console
app.post('/clean, async function(req, res, next) {

    // start proccess
    let result = await worker.process(data);

    // Send result when finish
    res.send(result);
});

// reply with when asked
app.get('/clean, async function(req, res, next) {
    res.send(worker.status);
});

问题是。服务器在POST /clean进程中工作如此努力,以至于GET /clean不能及时得到答复。

在工作人员完成其任务并释放处理器以响应请求之后,将答复所有GET /clean请求。

enter image description here

换句话说。应用程序在工作负载期间无法响应。

如何解决这种情况?

2 个答案:

答案 0 :(得分:1)

除了将您的服务转换为进程集群或使用诸如Worker Threads之类的实验性功能外,JS的单线程性质无法解决。

如果这些选项都不适合您,则需要定期放弃处理线程,以使其他任务可以处理某些事情:

function workPart1() {
  // Do a bunch of stuff
  setTimeout(workPart2, 10); 
}
function workPart2() {
  // More stuff
  setTimeout(workPart3, 10); // etc. 
}

答案 1 :(得分:1)

因为node.js以单线程方式运行Javascript(一次只能运行一个Javascript)并且没有时间片,只要您的worker.process()正在运行它的同步代码,就不能再有其他请求了由您的服务器处理。这就是worker.process()必须在运行时到达的任何HTTP请求之前完成的原因。在worker.process()完成之前,node.js事件循环很忙,因此它无法处理任何其他事件(例如传入的HTTP请求)。

这些是解决该问题的一些方法:

  1. 使用内置的集群模块对应用程序进行集群,以便您拥有一堆可以处理worker.process()代码或处理传入的HTTP请求的进程。

  2. 当需要调用worker.process()时,启动一个新的node.js进程,在该进程中运行该处理,并通过标准的进程间通信将结果传递回去。然后,您的主要node.js进程保持读取状态,以在传入的HTTP请求到达时立即处理它们。

  3. 创建一组其他的node.js进程的工作队列,这些进程运行放入队列中的作业,并将这些进程配置为能够从队列中运行worker.process()代码。这是#2的一种变体,它限制了进程的数量,并将工作序列化为一个队列(比#2更好控制)。

  4. 修改worker.process()的工作方式,使其一次可以完成几毫秒的工作,然后返回到消息循环,以便其他事件可以运行(例如传入的HTTP请求),并且然后一次又恢复几毫秒。这通常需要构建某种状态对象,该状态对象每次被调用时都可以一次完成一点工作,但是通常很难有效编程。

请注意,#1,#2和#3都需要在其他进程中完成工作。这意味着process.status()将需要从其他进程中获取状态。因此,您将需要某种与其他进程进行通信的进程间方式,或者需要将状态存储在可以从所有进程访问的存储中(例如redis),以便可以从那里进行检索。