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

SSR应用QPS估算与实际压测结果不符的疑问

SSR应用QPS估算与实际压测结果不符的疑问

嘿,我来帮你彻底理清楚这个困惑——你之前的QPS估算逻辑完全搞错了核心点:Node.js的异步操作是不阻塞事件循环的,咱们一步步拆解:

你原来的估算为什么错了?

你之前算的(1000ms - 200ms)/9ms这种逻辑,本质是把Node.js当成了“傻等异步操作完成再处理下一个请求”的同步阻塞模型,但Node.js的单线程是指事件循环是单线程,异步I/O(比如这里的setTimeout)是交给系统内核/线程池处理的,事件循环在等待异步结果的期间,是完全空闲的,可以立刻处理下一个请求。

举个简单的例子:第一个请求进来,执行到await setTimeout(...)时,Node.js会把这个200ms的定时器交给系统定时器模块,然后事件循环直接空出来,这时候第二个、第三个……第100个请求可以毫无阻碍地进来,同样执行到await时挂起定时器,事件循环继续处理新请求,完全不会等200ms再干活。

你的压测结果为什么远高于估算?

看你的ab压测参数:ab -n 100 -c 100 http://localhost:4000/test是同时发送100个请求,整个压测的总耗时是477ms,QPS达到209.84,这完全符合Node.js异步模型的表现:

  1. 前200ms:所有100个请求都快速进入服务端,执行到await setTimeout后挂起,事件循环处理完所有请求的前期逻辑后暂时空闲,等待定时器到期。
  2. 200ms后:所有定时器的回调同时进入事件队列,事件循环开始逐个处理这些回调:执行getServerSideProps剩余逻辑、渲染React组件(这部分是同步工作,每个请求耗时约4-9ms)、返回响应。
  3. 总耗时是200ms + 100个请求的同步总耗时,你的压测总耗时477ms,说明100个请求的同步总耗时约277ms,平均每个请求的同步耗时≈2.77ms,对应QPS=1000/(477/100)≈209,和压测结果完全匹配。

正确的QPS估算思路

要估算这种带异步操作的SSR应用QPS,核心看两个点:

  • 异步操作是否阻塞事件循环:像setTimeout、数据库查询、HTTP请求这类异步操作,都是不阻塞的,此时QPS的瓶颈是事件循环单位时间内能处理的同步任务总量(也就是渲染组件、处理回调的同步耗时),公式大概是QPS ≈ 1000ms / 单个请求的同步耗时(只要并发足够大,异步等待期间能把事件循环的“待处理同步任务”填满)。
  • 如果是同步阻塞的操作(比如大量计算、无异步的循环),那QPS才是1000ms / 单个请求的总耗时,因为此时事件循环被完全占满,无法处理其他请求。

结合你的代码:
你的getServerSideProps里的setTimeout是纯异步不阻塞的,所以当并发足够时,QPS只受限于每个请求的同步渲染耗时(6-9ms),压测结果里的平均同步耗时约4.76ms,所以QPS≈1000/4.76≈209,完全符合实际结果。

再补个直观的对比场景

如果你的getServerSideProps里不是setTimeout,而是一个需要200ms的同步计算(比如循环1亿次),那此时事件循环会被完全阻塞,100个请求的总耗时就是100*200ms=20000ms,QPS只有5,这才是你原来估算逻辑适用的场景——但这种场景在Node.js服务里几乎不会出现,因为我们都会把耗时操作改成异步的。

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 09:32:58