NodeJS事件循环Fundamendals

我相信这是一个常见的问题,但没有find具体的答案。

我有点理解NodeJS的基本概念,它是处理I / O的asynchronous/非阻塞性质。

为了说明起见,我们举一个简单的例子,在节点上写一个执行unix命令find /的HTTP服务器,并将结果写入http响应(因此在用户的浏览器上显示该命令的结果)。 我们假设这需要3秒钟。

假设有两个用户“A”和“B”通过他们的浏览器同时请求。

据我所知用户的请求排队在事件队列(消息A,消息B)。 该消息还具有一个处理完成后执行的相关callback的引用。

由于事件循环是单线程的,并逐个处理事件,

在我上面的例子中,“用户B”的callback触发需要6秒钟吗? [3用于“用户A”的事件处理,3用于它自己的事件处理]

这听起来像我在这里失去了一些东西?

最差的是,如果有100个用户在同一个毫秒内请求? 第100名赛事老板将成为最不幸的用户,必须等待永恒。

据我所知,在运行时只有一个事件队列,上述问题可以适用于应用程序任何部分的任何用户。 例如,网页X中的一个缓慢的数据库查询会减慢网页Y中的不同用户?

从根本上说,我发现串行处理事件和串行执行相关callback的问题。

我在这里错过了什么?

正确编写的node.js服务器将为任何networking,磁盘I / O,定时器或与其他进程的通信使用asynchronousI / O和通信。 这样写时,可以并行处理多个http请求。 尽pipe处理任何给定请求的node.js代码一次只能运行一个,但每当有一个请求正在等待I / O(通常是请求的大部分时间)时,其他请求就可以运行。

最终的结果是,所有的请求似乎都在同时进行(尽pipe实际上,这些请求是交织在一起的)。 Javascript事件队列是在所有各种请求之间序列化工作的机制。 每当一个asynchronous操作完成它的工作,或者希望通知某个事件的主JS线程,它将把事件放入事件队列中。 当JS执行的当前线程结束时(即使它正在进行自己的asynchronous操作),JS引擎将查找事件队列,然后执行该队列中的下一个项目(通常是某种forms的callback)方式,下一个排队的操作继续。

在你的具体例子中,当你启动另一个进程,然后asynchronous等待其结果时,当前的执行线程结束,然后事件队列中的下一个项目运行。 如果下一个项目是另一个http请求,则该请求开始处理。 当这第二个请求,然后命中一些asynchronous点,它的执行线程完成,并再次在事件队列中的下一个项目运行。 通过这种方式,新的http请求开始运行,asynchronous操作完成asynchronouscallback。 事件发生的顺序大致是FIFO(先进先出)顺序,如何放入事件队列。 我粗略地说,因为实际上有不同types的事件,并不是所有的事件都是连续的,但是为了讨论的目的,实现细节可以被忽略。

所以,如果有三个http请求到达同一时间,那么一个会运行,直到遇到一个asynchronous点。 然后,下一个将运行,直到它点击一个asynchronous点。 然后,第三个将运行,直到它达到asynchronous点。 然后,无论哪个请求完成第一个asynchronous操作,都将从该asynchronous操作获得一个callback,并且将一直运行,直到完成或点击另一个asynchronous点。 等等…

由于许多通常导致Web服务器花费大量时间来响应的通常是某种I / O操作(磁盘或networking),它们都可以在node.js中asynchronous编程,所以整个过程一般工作得很好,服务器资源比每个请求使用单独的线程更有效。 一次,它不能很好地工作,如果有一个沉重的计算密集型或长时间运行,而不是长时间绑定主要node.js线程的asynchronous操作。 因为node.js系统是一个合作的CPU共享系统,所以如果你有一个长时间运行的操作绑定了主节点.js线程,它会占用系统(根本就没有其他操作的先占式共享可以用multithreading系统)。 对系统进行pipe理使所有其他请求等待,直到第一个请求完成。 node.js回答一些CPU Hogging计算是将这个操作移动到另一个进程,并与node.js线程中的另一个进程asynchronous通信 – 从而保留单个node.js线程的asynchronous模型。


对于node.js数据库操作,数据库通常会为node.js编程提供一个asynchronous接口,以便以asynchronous方式使用数据库,然后由数据库接口的实现来实现以asynchronous方式实现接口。 这可能是通过与实际的数据库逻辑实现(可能通过TCP通信)的其他进程进行通信来完成的。 那实际的数据库逻辑可能使用实际的线程或者不是 – 这是一个实现细节,直到数据库本身。 对node.js来说重要的是,计算和数据库工作不在其他某个进程的node.js线程中,甚至可能在另一个主机上,所以它不会阻塞node.js线程。