NodeJS eventLoop + ExpressJS在单路由上并发请求的意外行为



我有一个简单的快递应用程序,有一个单一的路由:

const express = require("express");
const app = express();
const crypto = require("crypto");
app.get('/', (req, res, next) => {
const start = new Date()
console.log('Start timestamp', `${start.getTime()}`);
crypto.pbkdf2('foo', 'bar', 800000, 512, 'sha512', () => {
console.log('End diff ', new Date()- start)
res.send('Success')
})
})
app.listen(3000);

我在本地主机上运行这个应用程序。单次请求时间接近3.2秒。我的Mac M1有8个CPU内核。预计当我在我的应用程序'/'路由上得到4个并发请求时,它们将通过4хthreadPool运行,并分成4个不同的/分离的内核。

但是当我发送这4个并发请求时,我有下一个console.log:

Start timestamp 1653231979628
End diff  3256
Start timestamp 1653231982889
Start timestamp 1653231982889
Start timestamp 1653231982889
End diff  3437
End diff  3438
End diff  3439

因此,首先运行一个请求,它冻结事件循环,在它完成后,其他3个请求将同时处理。

对我来说最有趣的是,当我用pm2作为4个分离的节点实例运行这个应用程序时,这种行为是相同的。但是怎么可能呢,特别是在运行4个不同的pm2实例的情况下?

Node.js是一个单线程事件循环。在您的示例中,事件有两种类型:

。传入请求

  • 记录开始时间戳。
  • 加密操作启动。
  • 等待下一个事件

B。加密操作完成

  • 回调函数被调用。
    • 记录结束时间戳
    • "Success"消息作为响应发送。
  • 等待下一个事件

在您运行的4个请求中,事件顺序为A1, B1, A2, A3, A4, B2, B3, B4。下一个事件是A还是B还取决于执行加密操作的速度。

最新更新