You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Node.js事件循环疑问:高并发下Poll与Check阶段执行顺序

原问题

假设我的Web应用非常受欢迎,Node.js服务器每秒处理数千请求,每个请求回调都会调用setImmediate(cb)。我认为setImmediate回调没有机会执行,因为事件循环因Poll阶段每秒都有大量请求回调,无法进入Check阶段,这是否正确?我进行了如下模拟:

客户端代码

for(let i = 1; i <= 50; i++) {
  const fetchData = async () => {
      const data = await fetch('http://127.0.0.1:3000');
      console.log(data + ' ' + i);
  }
  fetchData()
}

服务端代码

const express = require('express');
const fs = require('fs');
const cors = require('cors');
const app = express();
app.use(cors())
let num = 0;
app.get('/', (req, res) => {
    num = num + 1;
    console.log(`the request number is: ${num}`);
    res.status(200).send('hello from the server');
    setImmediate(() => {
        console.log('hello i am from setImmediate ' + num )
    })
})
app.listen(3000, () => {
    console.log('server is listening')
})

Node.js文档说明,事件循环进入Poll阶段会执行回调队列中所有回调,队列清空后才进入Check阶段执行setImmediate回调。但我的模拟中,发送50个请求后,本该有50个请求回调在Poll阶段,实际却是完成一个请求回调就执行对应的setImmediate回调,再处理下一个请求回调,这与文档描述不符,求解释。


解答

核心结论

你的初始假设错误——高并发场景下,setImmediate回调不会因为Poll阶段持续有请求回调而永远无法执行。

事件循环Poll阶段的实际运行逻辑

Node.js文档的描述是简化版的理想状态,实际运行受libuv调度机制限制:

  • Poll阶段不会一次性处理所有堆积的回调,每次事件循环迭代会处理一批回调(数量由libuv内部阈值控制),防止单个阶段长时间占用事件循环导致其他阶段饥饿。
  • 当Poll队列处理到一定程度,或者有setImmediate回调待执行、定时器到期时,事件循环会退出Poll阶段,依次进入Check、Timers等阶段处理对应任务。

模拟现象的原因

你看到的“逐个执行请求回调后立刻跑setImmediate”,主要是两个因素:

  1. 浏览器并发限制:浏览器对同一域名的并发请求有默认限制(通常6-8个),50个fetch请求是分批发送到服务器的,并非一次性全部进入Poll队列。每处理完一个请求回调,事件循环会自然推进到Check阶段执行对应的setImmediate,再回到Poll阶段处理下一批请求。
  2. 请求回调的执行粒度:每个HTTP请求的回调是独立的事件循环任务,单个回调执行完毕后,当前迭代会继续走完全部阶段,而非停留在Poll阶段等待所有请求。

验证高并发场景的正确方式

如果要模拟“大量请求回调堆积在Poll阶段”,应该用压测工具(如ab -n 1000 -c 100 http://127.0.0.1:3000),或者在服务端内部批量生成回调:

app.get('/batch', (req, res) => {
  for (let i = 0; i < 100; i++) {
    // 用process.nextTick模拟Poll阶段的回调堆积
    process.nextTick(() => {
      console.log(`Poll callback ${i}`);
      setImmediate(() => console.log(`setImmediate ${i}`));
    });
  }
  res.send('done');
});

此时你会看到:先批量执行完所有Poll阶段的回调,再一次性执行所有setImmediate回调,这才符合文档描述的理想场景。


内容的提问来源于stack exchange,提问作者Junaid Arshad

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 12:43:28