我正在研究 Node JS 如何提高多个并发请求的性能!在阅读了几个博客后,我发现:
- 当任何请求到来时,都会触发一个事件,并将相应的回调函数放入事件队列中。
- 一个事件循环(主线程)负责处理事件队列中的所有请求。如果请求使用非阻塞 I/O,事件循环处理请求并发回响应。
- 如果请求包含阻塞 I/O 事件循环在内部将此请求分配给工作池中的空闲工作人员,并且当工作人员发回结果时,事件循环发送响应。
我的问题是由于事件循环使用 libuv 库在内部将繁重的阻塞工作传递给工作池,为什么我们需要异步回调?
为了更好地理解,请参阅以下代码:
const express = require('express')
const app = express()
const port = 3000
function readUserSync(miliseconds) {
var currentTime = new Date().getTime();
while (currentTime + miliseconds >= new Date().getTime()) {
}
return "User"
}
async function readUserAsync(miliseconds) {
var currentTime = new Date().getTime();
while (currentTime + miliseconds >= new Date().getTime()) {
}
return "User"
}
app.get('/sync', (req, res) => {
const user = readUserSync(80)
res.send(user)
})
app.get('/async', async (req, res) => {
const user = await readUserAsync(80)
res.send(user)
})
app.listen(port, () => {
console.log(`Example app listening at http://localhost:${port}`)
})
我使用 apache 基准测试工具检查了两个端点的性能,假设每个 I/O 操作需要 80 毫秒。
ab -c 10 -t 5 "http://127.0.0.1:3000/async/"
ab -c 10 -t 5 "http://127.0.0.1:3000/sync/"
令人惊讶的是,具有异步回调的端点每秒的请求数更高。
那么事件循环、线程池和异步等待如何在内部工作以处理更多并发请求呢?