Node JS多个并发请求到后端API
Node JS multiple concurrent requests to backend API
这是我的节点 js 后端 API 方法。
apiRouter.route('/makeComment')
.post((req, res) => {
consoleLogger.info("Inside makeComment API..");
logger.info("Inside makeComment");
let timestamp = new Date().getTime();
let latestCommentID = timestamp.toString();
console.log("comment ID generated is "+latestCommentID);
res.json({
'makeComment': 'success',
'commentid':latestCommentID
});
});
现在,如果有多个并发请求来到这个API,会发生什么?
根据我的理解,NodeJS 会为请求维护一个Event Queue,一个一个地处理请求。
因此,不可能为两个不同的请求获得相同的时间戳。
请问我的理解是否正确?
编辑 1:
谷歌搜索了一段时间后,得到了这个link,它清楚地解释了一些概念。
这里没有并发的可能。正如您正确学习的那样,Node.js 在 single-threaded 环境中运行(除非您使用 clusters, the worker API, or other related Node.js modules that facilitate IPC)。因此,行
let timestamp = new Date().getTime();
不能被两个同时运行线程并发调用,上面提到的例外情况除外。
但是,Date.prototype.getTime()
只有毫秒分辨率,因此事件循环可能会在同一毫秒内从两个未决的异步请求中顺序调用对 apiRouter.route('/makeComment').post()
的回调。
您完全可以在 2 个并发调用上得到相同的时间戳。但这不是因为 NodeJS 或您的服务器并行处理请求,而是因为一毫秒的时间足够长,您的服务器可以在同一毫秒内处理许多请求。
Multi-threaded 与并发
您已经正确地识别出并发性和 multi-threading 之间微妙但重要的区别。在 multi-threaded 环境中,两个不同的操作确实可以同时发生在 CPU 的 2 个不同核心上。在并发但 single-threaded 环境中,事情确实按顺序发生,希望以 non-blocking 方式发生,而且非常快!
Javascript 是单线程环境。是的,它有一个事件循环,它将任务排队并一次处理一个任务。 NodeJS(以及浏览器 Javascript 应用程序中的 Web API)提供某些异步功能,例如 fs.writeFile
或 fetch
,运行 与 [=45] 合作=] 可能以相同或不同的方式执行 thread/core,然后通过回调和 Promises 将返回结果编排回您的应用程序。
对于您的示例,您的处理程序(从 (req, res) => { ... }
开始的部分)仅包含同步调用。所以,是的,对这个处理程序的各种调用将 运行 依次进行,一个接一个。而且,虽然此处理程序的两个 运行 不会真正在 相同的 时间发生,但它们会发生得非常快,并且您可能会遇到这样的情况来自 Date 对象的相同毫秒值。如果您有更高分辨率的可用时间戳(可能是纳秒),或者如果您的处理程序花费了更长的时间 运行(例如,您 运行 一个 for
循环了十亿次迭代),那么您将能够更清楚地观察顺序行为。
避免在 single-threaded 应用程序中阻塞(同步)调用
这就是为什么建议您不要在 NodeJS Web 服务器中执行任何同步 IO 操作(例如 fs.writeFileSync
等)的确切原因,因为当一个请求执行阻塞 IO 操作时,所有其他请求请求正在等待,在事件循环中排队。
关于 Javascript 事件循环的非常好的视频;这应该阐明一些主题:https://www.youtube.com/watch?v=8aGhZQkoFbQ
这是我的节点 js 后端 API 方法。
apiRouter.route('/makeComment')
.post((req, res) => {
consoleLogger.info("Inside makeComment API..");
logger.info("Inside makeComment");
let timestamp = new Date().getTime();
let latestCommentID = timestamp.toString();
console.log("comment ID generated is "+latestCommentID);
res.json({
'makeComment': 'success',
'commentid':latestCommentID
});
});
现在,如果有多个并发请求来到这个API,会发生什么?
根据我的理解,NodeJS 会为请求维护一个Event Queue,一个一个地处理请求。
因此,不可能为两个不同的请求获得相同的时间戳。
请问我的理解是否正确?
编辑 1:
谷歌搜索了一段时间后,得到了这个link,它清楚地解释了一些概念。
这里没有并发的可能。正如您正确学习的那样,Node.js 在 single-threaded 环境中运行(除非您使用 clusters, the worker API, or other related Node.js modules that facilitate IPC)。因此,行
let timestamp = new Date().getTime();
不能被两个同时运行线程并发调用,上面提到的例外情况除外。
但是,Date.prototype.getTime()
只有毫秒分辨率,因此事件循环可能会在同一毫秒内从两个未决的异步请求中顺序调用对 apiRouter.route('/makeComment').post()
的回调。
您完全可以在 2 个并发调用上得到相同的时间戳。但这不是因为 NodeJS 或您的服务器并行处理请求,而是因为一毫秒的时间足够长,您的服务器可以在同一毫秒内处理许多请求。
Multi-threaded 与并发
您已经正确地识别出并发性和 multi-threading 之间微妙但重要的区别。在 multi-threaded 环境中,两个不同的操作确实可以同时发生在 CPU 的 2 个不同核心上。在并发但 single-threaded 环境中,事情确实按顺序发生,希望以 non-blocking 方式发生,而且非常快!
Javascript 是单线程环境。是的,它有一个事件循环,它将任务排队并一次处理一个任务。 NodeJS(以及浏览器 Javascript 应用程序中的 Web API)提供某些异步功能,例如 fs.writeFile
或 fetch
,运行 与 [=45] 合作=] 可能以相同或不同的方式执行 thread/core,然后通过回调和 Promises 将返回结果编排回您的应用程序。
对于您的示例,您的处理程序(从 (req, res) => { ... }
开始的部分)仅包含同步调用。所以,是的,对这个处理程序的各种调用将 运行 依次进行,一个接一个。而且,虽然此处理程序的两个 运行 不会真正在 相同的 时间发生,但它们会发生得非常快,并且您可能会遇到这样的情况来自 Date 对象的相同毫秒值。如果您有更高分辨率的可用时间戳(可能是纳秒),或者如果您的处理程序花费了更长的时间 运行(例如,您 运行 一个 for
循环了十亿次迭代),那么您将能够更清楚地观察顺序行为。
避免在 single-threaded 应用程序中阻塞(同步)调用
这就是为什么建议您不要在 NodeJS Web 服务器中执行任何同步 IO 操作(例如 fs.writeFileSync
等)的确切原因,因为当一个请求执行阻塞 IO 操作时,所有其他请求请求正在等待,在事件循环中排队。
关于 Javascript 事件循环的非常好的视频;这应该阐明一些主题:https://www.youtube.com/watch?v=8aGhZQkoFbQ