【发布时间】:2015-08-13 17:55:58
【问题描述】:
我确定这是一个常见问题,但没有找到具体答案。
我有点理解 NodeJS 的基本概念,以及它处理 I/O 的异步/非阻塞性质。
为了论证,让我们举一个简单的例子,一个用 node 编写的 HTTP 服务器,它执行 unix 命令 'find /' 并将结果写入 http 响应(因此在用户的浏览器上显示命令的结果)。 假设这需要 3 秒。
假设有两个用户“A”和“B”同时通过他们的浏览器请求。
据我了解,用户的请求在事件队列(消息 A、消息 B)中排队。该消息还具有对其关联的回调的引用,一旦处理完成就会执行。
由于事件循环是单线程的,并且会一一处理事件,
在我上面的例子中,触发“用户 B”的回调需要 6 秒吗? [3个用于“用户A”的事件处理,3个用于它自己的事件处理]
这听起来好像我在这里遗漏了什么?
最糟糕的是,如果有 100 个用户在同一毫秒请求?第 100 位活动所有者将成为最不幸的用户,必须等待永恒。
据我了解,运行时只有一个事件队列,上述问题适用于应用程序任何部分的任何用户。例如,网页 X 中的慢速数据库查询会减慢网页 Y 中的其他用户的速度?
从根本上说,我发现事件的串行处理和相关回调的串行执行存在问题。
我错过了什么吗?
【问题讨论】:
-
当 node 告诉 shell 执行
find /时,它只会启动一个新进程。您可以同时运行多个进程(在节点之外)。节点的异步部分只是意味着它将等待这些操作完成,同时继续处理其他事情,然后开始服务。 A 和 B 都会等待大约 3 秒的响应。 -
感谢您的回复,所以如果为每个请求启动一个新进程,我的理解是否正确:“事件处理将并行发生,但这些事件处理的回调是串行的” .因此,事件循环将被阻止的唯一实例是在回调中具有“睡眠功能”。
-
如果您执行同步操作,该进程将被阻止,例如,
fs.readFileSync。此外,在这种情况下,事件处理实际上只并行发生,因为节点进程没有这样做。 -
嗯好的。如果必须将其扩展到数据库查询示例,
db.executeQuery('select * from employees', function(rows) { // Do something with rows. });NodeJS 的职责只是提供一个基础设施来以非阻塞(或异步)方式执行数据库查询。现在由数据库(库或模块)负责在新线程中运行查询以避免事件处理被阻塞。这是一个公平的说法吗? -
是的,它就是这样工作的。查询将由数据库执行。然后,一旦数据库响应,节点将处理回调:
function (rows)。
标签: javascript node.js dom-events event-loop