我知道过去已经在很多细节(How is Node.js inherently faster when it still relies on Threads internally?)中讨论过这个问题,但我仍然无法正确理解node.js事件循环模型,并且它是一个单线程模型如何处理并发请求。
Uptil现在我的理解是:我们收到IO请求 - > node.js在内部生成一个线程,并将IO请求传递给它 - >因为这是一个IO请求所以CPU将它交给DMA控制器并释放这个线程 - >此线程再次进入线程池以提供不同的请求 - > DMA仍在执行IO,一旦DMA获取所有数据,就会触发某种事件 - >此事件由node.js系统捕获,它将提供的回调函数放在事件循环上 - >每当事件循环获得机会时,它就对IO提取的数据执行回调 - >由于闭包,回调函数仅对回调获取的数据执行
所以这个过程反复进行。请有人澄清我的理解并提供一些信息
答案 0 :(得分:1)
只有一个线程(主线程)用于处理网络I / O(文件I / O略有不同,因为并非所有平台都提供可用的异步,非阻塞文件I / O API,因此在线程池中的那些平台上使用同步文件I / O API。
因此,当网络请求进入时,它们全部由主线程处理(主要通过libuv)epoll / kqueue / IOCP /等。用于检测(以非阻塞方式)数据可用时(或者当存在传入TCP连接时)。如果有可用数据,则根据需要适当调用javascript,传递套接字数据。如果套接字上没有数据(事件循环没有其他事情可做,例如触发定时器),则执行进入事件循环的下一次迭代,其中进程重新开始。
就将套接字数据与套接字javascript对象相关联而言,它是C ++包装器对象(例如tcp_wrap
,udp_wrap
等)和javascript对象的组合,以确保数据到达适当的地方。
这是一个稍微旧一点的图表,解释了节点事件循环的单个周期中发生的事情。其中一些可能自节点v0.9以来略有改变,但它可以让你了解一般的想法:
答案 1 :(得分:0)
node.js有一个单线程模型,不需要锁和信号量(在传统的多线程模型中使用)。锁和信号量可以在性能方面增加一些成本,更重要的是,可以提供很多绳索来悬挂自己(换句话说,许多陷阱)。 IO操作是并行发生的,因为IO之间的工作通常非常小,这种单线程模型通常可以很好地工作。
(旁注:如果你有一个在IO操作之间做很多工作的应用程序,即CPU密集型应用程序,那就是节点不能很好地扩展的情况)
我喜欢考虑为什么节点模型能够很好地扩展的论点与人们认为NoSQL比SQL数据库更好地扩展的原因相同。显然是Java(多线程)和SQL规模;像Facebook和Twitter这样的大公司已经证明了这一点。但是,就像在SQL中一样,有很多事情你可以做错误地降低你的性能。 Node.js并没有消除所有潜在的问题,它只是很好地限制了许多常见原因。