异步setTimeout会阻止处理,直到发生重新发送

时间:2019-04-04 20:43:04

标签: javascript node.js express

我有一个异步操作,该操作被委派给工作进程。

由于每个操作大约需要2秒钟,因此我想在请求响应中传递该操作的结果。

我将工作进程的执行包装在一个promise中,直到工作进程完成CPU密集型工作并返回结果后,该承诺才会解决:

module.exports = (req, res, controller) => {
  res.setHeader('Content-Type', 'application/json');

  const workerService = controller.services.workers;
  if (!workerService) {
    return res.json({
      ok: false,
      info: 'Worker service has not been started. Relaunch API server and check logs.'
    });
  }

  let commandObject = '';
  try {
    const postBody = req.body;
    // build a backtest execution command based on request params
    commandObject = getWorkerCommandFromPostBody(postBody);

  } catch (exception) {
    return res.json({
      ok: false,
      info: exception
    });
  }

  return controller.services.workers
    .promiseWorkerExecution(commandObject)
    .then(result => {
      if (result.context && result.context.results) {
        return res.end(result.context.results);
      }

      return res.end(result);
    })
    .catch(e => res.end(e));
}

这是我感到困惑的地方。我的Express进程正在运行的主线程不会被阻塞。整个密集操作都委托给专用的子流程(通过“集群”模块)。

但是,如果我触发了这些请求中的3个,则第二个请求甚至不会开始处理,直到第一个请求看到res.end()。纯粹是在等待诺言解决。我确信可以在等待setTimeout几秒钟后解决的情况下重现这一点。

这是预期的吗?我以为我可以将其视为异步操作,并且当我准备好时,可以在Promise解决时发送此请求响应。

是否没有办法在快速服务器上也不运行集群就可以继续接受对快速服务器的并行请求?我希望有一个快递服务器,并有单独的(上限)工作人员来委派/处理CPU密集型工作。

我需要跟踪并行运行的操作数,因此,理想情况下,我不希望有单独的快递服务...有人对此有建议吗?

编辑:我应该补充一点,我知道Node的单线程性质,但是我认为事实承诺只要不阻塞线程就允许并行异步操作...

编辑:我仅使用setTimeout在沙箱中重现了该问题,以延迟重新发送。

大家好,所以setTimeout可以重现,这显然不是CPU密集型阻塞任务。沙箱: https://codesandbox.io/embed/nr41lkw95j

我正在通过在终端中触发此请求来测试3个并行请求: curl https://nr41lkw95j.sse.codesandbox.io/test && curl https://nr41lkw95j.sse.codesandbox.io/test && curl https://nr41lkw95j.sse.codesandbox.io/test

沙盒服务器上的终端显示它正在阻止请求处理,直到当前请求发送响应为止,即使异步回调中正在发生

1 个答案:

答案 0 :(得分:2)

问题在于您如何运行请求,而不是并行运行请求。

s

当您使用/* TO BE DONE START */ while (isspace((unsigned char)*q)) q++; *q = toupper((unsigned char)*q)); puts(s); /* TO BE DONE END */ 时,它将等待直到正确执行了最后一个命令,而不会触发执行下一个命令的错误。如果要并行运行请求,则必须执行以下操作:

curl https://nr41lkw95j.sse.codesandbox.io/test && curl https://nr41lkw95j.sse.codesandbox.io/test && curl https://nr41lkw95j.sse.codesandbox.io/test

只有一个&&,因此它在后台运行。

一种替代方法是使用apache基准测试或类似程序。

curl https://nr41lkw95j.sse.codesandbox.io/test &
curl https://nr41lkw95j.sse.codesandbox.io/test &
curl https://nr41lkw95j.sse.codesandbox.io/test &

以上命令总共执行9个请求,并发3。 运行它,您将看到:

&

这证明了Node.js可以并发处理多个请求,除非您阻止事件循环。