Node.js单线程?如果有大量并发请求,它是如何工作的?

5

我是新手学习nodejs,目前正在学习它。 我知道nodejs是单线程的,但我想知道:如果我使用非阻塞方法, 例如,有20000个并发请求,其中一个请求需要花费很长时间,而其他请求只需要短时间。

那么一旦我们遇到长时间的请求,nodejs会说“嗨,请暂停,其他请求需要使用”,nodejs是否有默认的时间来检测是否需要暂停?请纠正我使用错误的单词“暂停”(因为我认为由于它是单线程,所以应该停止计算一个请求,如果另一个请求要被处理)。

在我假设的情况下,那么长时间的请求需要很多时间才能被处理吗?


如果那个需要很长时间的任务执行了许多同步操作,那么会有问题,但如果它是异步的,比如读取或写入文件,其他请求将在等待异步操作完成时继续处理。JavaScript在事件循环中运行。因此,在为请求提供服务的Node.js应用程序中,应避免使用同步操作。 - Kevin B
1
这里有一个类比。Node.js就像是一个国王,坐在他的宝座上,仆人们带着请求来寻求回应。国王一次只听取一个请求,并且一次只回应一个请求。然而,他有很多仆人来为他工作。仆人A立即进来,紧接着是仆人B。国王先听取了仆人A的请求,然后派他去拿咖啡。然后他听取了仆人B的请求,并派他去打开窗户。如果仆人B在仆人A之前回来,那么仆人B将会被先解雇,而国王仍在等待仆人A。当仆人A回来时,国王将解雇他2个。 - Kevin B
1
为什么会有负评?仅仅因为提问者不理解node.js的工作原理并不足以导致负评。在我看来,这是一个合理的问题。+1 - Maroshii
@Maroshii 谢谢大家 - adiggo
显示剩余4条评论
1个回答

10

虽然Node.js只能同时接收或响应一个请求,但它可以同时处理多个请求。

例如,假设您有一个Node.js应用程序,它是一个REST API,并且除端点C之外的每个请求都会导致对数据库的调用。 REST API有3个端点。

端点A:需要3秒钟才能与数据库通信

端点B:需要2秒钟才能与数据库通信

端点C:不与数据库通信,只返回静态文本。

不可能同时发生多个请求。无论时间戳有多接近,始终有一个请求先到达。

现在,假设我们有10个请求同时发生,顺序如下:

ABCBCCAABC

以下是它们将接收和响应的方式:

REC:A
REC:B
REC:C
RESP:C
REC:B
REC:C
RESP:C
REC:C
RESP:C
REC:A
REC:A
REC:B
REC:C
RESP:C
// 2 seconds later
RESP:B
RESP:B
RESP:B
// 1 second later
RESP:A
RESP:A
RESP:A

由于 C 没有执行任何异步操作,因此它总是立即发生。然后你会先收到 B 的所有内容,然后才是 A,因为 B 比 A 快。

但是,基于数据库设置,B 和 A 的顺序可能会有所不同,例如,如果它只处理 x 个查询。

如果我们引入一个执行需要 6 秒钟的同步操作的终端点 D,你将得到以下结果:

ADABC

REQ:A
REQ:D
// 6 long seconds later...
RESP:D
REQ:A
REQ:B
REQ:C
RESP:C
// 2 seconds later...
RESP:B
// 1 second later...
RESP:A
RESP:A

D会在同步操作进行时停止所有的JavaScript处理。如果有1个端点执行了同步操作,那么它很容易成为一个故障点,导致有人阻断您的API。


好的,我明白了。但我有一个问题。与其他语言“一旦有新请求进来就使用新线程”的方式相比,它有什么优势?我看到区别在于I/O部分。但是这有什么优势呢? - adiggo
我不认为我能真正回答这个问题,而且我怀疑这也不是一个“一刀切”的答案,因为每种方法都有其自身的优缺点。 - Kevin B
是的,你说得对。但我看到很多人说它可以避免竞态条件,避免浪费时间在死锁上。但我仍然认为可能会存在竞态条件,因为每个请求的内部处理仍然是并发的。 - adiggo
如果你不正确编码,肯定会发生竞态条件。根据我对Node.js API的少量经验来看,与ColdFusion相比,Node.js API更加冗长,我必须编写更多的代码来使其正常工作(当然,还有一些模块,如Express和Loopback可以为您完成这个工作)。 - Kevin B
1
请记住,仅因为node.js是单线程的,并不意味着您不能为单个应用程序使用多个线程。例如,我在4个集群中运行我的API,每个CPU一个。请求会自动分配给这4个应用程序,由于我正在使用数据库表进行会话管理,因此所有4个应用程序都可以访问会话数据。如果您的数据库位于单独的服务器上,则可以轻松添加更多服务器(在负载均衡器后面)运行更多集群而无需更改任何内容。 - Kevin B
@KevinB 哇,没错。我刚开始学习Node.js,相比其他语言确实有点啰嗦。你提供的不同集群的例子也很好。 - adiggo

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接