【问题标题】:Concurrency in node js express app for get request with setTimeout节点 js express 应用程序中的并发用于使用 setTimeout 获取请求
【发布时间】:2021-04-06 17:32:22
【问题描述】:

Console log Image

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

app.get('/', async (req, res) => {
  console.log('got request');

  await new Promise(resolve => setTimeout(resolve, 10000));

  console.log('done');
  res.send('Hello World!');
});

app.listen(port, () => {
  console.log(`Example app listening at http://localhost:${port}`);
});

如果我同时点击 get request http://localhost:4444 三次,那么它会返回如下日志

got request
done
got request
done
got request
done

由于节点事件循环和回调队列在进程线程之外,它不应该以下面的方式返回输出吗? (也许我错了,但需要对节点内部有一些了解)和节点中的外部 api 请找到附图 Javascript Run time environment

got request
got request
got request
done
done
done

【问题讨论】:

  • 是的,它应该和它完全按照你提到的方式做,在浏览器中检查,ibb.co/g4P40Sc 不仅如此,它在常规快递 js 应用程序中也做同样的事情! ibb.co/YpxNGTj
  • @programcoder19 很奇怪,但是当我运行相同的东西时,我得到了这个作为输出 [link]ibb.co/mDMR0qf
  • 它是节点版本吗?我使用的是 12.3.1 版
  • 没有用最新的节点版本测试过,没有返回预期的输出

标签: node.js concurrency settimeout


【解决方案1】:

感谢https://stackoverflow.com/users/5330340/phani-kumar

我知道它阻塞的原因。我在 chrome 中对此进行了测试。我正在从 chrome 浏览器发出 get 请求,当我在 Firefox 中尝试相同时,它按预期工作。

原因是因为这个

Chrome 会锁定缓存并等待查看一个请求的结果,然后再再次请求相同的资源。

Chrome stalls when making multiple requests to same resource?

【讨论】:

    【解决方案2】:

    它正在返回这样的响应:

    Node.js 是事件驱动语言。要了解并发性,您应该查看 How 节点正在执行此代码。 Node 是一种单线程语言(但在内部它使用多线程),它在请求到来时接受请求。在这种情况下,Node 接受请求并为 Promise 分配回调,但是,在等待事件循环执行回调的同时,它会接受尽可能多的请求(例如内存、cpu 等)。 )。由于事件循环中有 setTimeout 队列,所有这些回调都将在那里注册,一旦计时器完成,事件循环将耗尽其队列。

    单线程事件循环模型处理步骤:

    • 客户端向 Node.js 服务器发送请求。

    • Node.js 内部维护一个有限的(可配置的)线程池来为客户端请求提供服务。

    • Node.js 接收这些请求并将它们放入一个称为“事件队列”的队列中。

    • Node.js 内部有一个组件,称为“事件循环”。它之所以得这个名字是因为它使用无限循环来接收请求并处理它们。

    • 事件循环仅使用单线程。它是 Node JS 平台处理模型的主要核心。

    • 事件循环检查任何客户端请求是否放置在事件队列中。如果没有,则无限期地等待传入的请求。

    • 如果是,则从事件队列中提取一个客户端请求

      • 启动客户端请求的过程

      • 如果该客户端请求不需要任何阻塞 IO 操作,则处理所有内容,准备响应并将其发送回客户端。

      • 如果该客户端请求需要一些阻塞 IO 操作,例如与数据库、文件系统、外部服务交互,那么它将采用不同的方法

    • 检查内部线程池中的线程可用性

    • 选择一个线程并将此客户端请求分配给该线程。

    • 该线程负责接收该请求、处理它、执行阻塞 IO 操作、准备响应并将其发送回事件循环

    你可以在这里查看更多details(很好解释)。

    【讨论】:

    • 感谢@Apoorva Chikara 的解释。我也同意代码应该以异步方式运行。但在我的情况下并没有发生。请参考上面的截图。它正在阻止此代码ibb.co/mDMR0qf。有什么方法可以检查内部线程的可用性吗?也许内部线程不可用。
    • 如果这解释了您可以接受并支持的问题。
    • 对不起 Apoorva Chikara,我的问题是为什么我在阻止自然时得到响应。我在我的问题中添加了状态图,我很熟悉它本质上应该是非阻塞的。答案是由于 chrome 的阻塞或停滞性质,它的工作方式不同。感谢您的回答帮助整个社区。我确实赞成它,但不能接受它作为答案。
    • 很高兴看到答案!
    猜你喜欢
    • 1970-01-01
    • 2015-09-15
    • 2017-03-09
    • 2021-03-07
    • 2014-01-27
    • 1970-01-01
    • 2020-12-19
    • 1970-01-01
    相关资源
    最近更新 更多