rah*_*mar 8 event-loop node.js
Node.js维护一个事件循环,但是默认情况下,它还具有四个线程来处理复杂的请求。当线程池中有更多可用线程时,如何使用单线程?
而且,事件循环为复杂任务分配的线程是专用线程,那么它与其他多线程概念有何不同?
我就简单明了的讲一下,消除大家的困惑:
\n节点的事件循环是单线程的,但其他进程不是。
\n混乱来自于 Node 在底层使用的 C++(NodeJS 大约是 30% JS + 70% C++)。因此,默认情况下 NodeJS 的 JS 部分是单线程的,但它使用 C++ 的线程池。因此,如果需要异步 I/O 操作,我们有一个单线程 JS,它是 NodeJS 的事件循环+ 4 个 C++ 线程。
\n同样重要的是要知道事件循环就像一个流量组织者,每个请求都会经过循环(这是单线程的)。如果需要 I/O 进程,事件循环会将这些请求组织到池线程。如果您有繁重的图像处理、视频编辑、音频处理或 3D 图形等高计算任务(大多数应用程序不需要),那么 NodeJS 将成为您的瓶颈。\nNodeJS 很出色适用于执行处理数据库和文件系统等任务的 I/O 绑定应用程序(大多数应用程序都是这种情况)。
\n同样,默认情况下,NodeJS 使用 4 个线程池(加上事件循环本身的一个线程)——总共 5 个线程。
\n一般来说,CPU 可以包含一个或多个核心,这取决于您的服务器(金钱)。
\n每个核心可以有线程。观察您的活动监视器并了解您正在使用多少个线程。
\n每个进程都有多个线程。
\nNode的多线程是因为node依赖于V8和libuv(C库)。
\n长话短说——
\n节点的事件循环本身是单线程的,但有许多操作是在事件循环之外完成的(例如加密和文件系统)。如果您有两次对 crypto 的调用,那么它们中的每一个都会到达一个 THREAD(想象 3 次对 crypto 的调用,1 次对 fs 的调用,这些调用将从线程池中的 4 个线程中为每个线程分配一个)。
\n最后:通过更改process.env.uv_threadpool_size的值,可以很容易地增加 C-Library libuv 线程池的默认线程数(默认为 4)。此外,您还可以使用集群(推荐 PM2)来克隆事件循环并拥有多个事件循环,以防单线程循环不足以满足您计算量大的应用程序的需要。
\n因此,没有人说明线程池是 C++ 的东西,\xe2\x80\x99s 受 NodeJS 控制,并且大多数情况下不应该由开发人员控制。
\n希望这能让事情变得简单。
\n在您所指的上下文中,“单线程”表示Javascript作为单个线程运行。 无论是字面上还是按时间片,都没有两个Javascript同时运行。这极大地简化了Javascript开发,因为不需要对在不同Javascript之间共享的Javascript变量进行线程同步,因为只能同时运行一个Javascript。
综上所述,node.js确实使用其实现内部的线程。您提到的默认四个线程在磁盘I / O的线程池中使用。由于磁盘I / O通常是在操作系统级别上的同步操作,会阻塞调用线程,并且node.js的设计应将所有I / O操作都提供为异步操作,因此node.js设计者决定采用异步接口通过使用线程池来实现(以本机代码)fs模块磁盘I / O接口(是的,在某些操作系统中存在非阻塞磁盘I / O操作,但是node.js设计者决定不这样做)。使用它们)。这一切都是在本机代码的幕后进行的,并且不会影响Javascript仅在单个线程中运行的事实。
这是在node.js中磁盘I / O调用如何工作的摘要。假设已经有一个打开的文件句柄。
fs.write()
现有文件句柄。fs.write()
调用返回fs.write()
调用之后出现的所有语句fs.write()
线程上的本机代码调用完成。它获取一个保护事件循环的互斥锁,并将一个事件插入事件队列。因为直到执行完当前的Javascript流才执行新事件,所以Javas获得的位置是事件驱动的单线程性质,即使可以使用本机代码线程来实现某些库函数。这些线程用于将阻塞操作变为非阻塞操作,但不会影响Javascript执行本身的单线程性能。
这里的关键是node.js是事件驱动的。触发某些Javascript运行的每个新操作都将通过事件队列进行序列化,直到当前Javascript流完成执行后,才处理下一个事件。
在node.js架构中,要使两个Javascript独立运行并同时运行的唯一方法是为每个Javascript使用单独的node.js进程。然后,它们将作为两个完全独立的操作运行,并且操作系统将对其进行单独管理。如果您的计算机至少有两个核心,那么它们实际上可以同时运行,每个核心都在自己的核心上。如果您的计算机只有一个内核,则它们实际上将位于它们自己的进程线程中,并且操作系统会对其进行时间片(在它们之间共享一个CPU)。
默认情况下, JavaScript 代码的执行在单个线程上运行。
然而,node.js 尝试使大多数长时间运行的调用异步。对于某些只涉及执行异步操作系统调用,但对于其他一些,node.js 将在辅助线程上执行调用本身,同时继续运行其他 JS 代码。一旦异步调用终止,Js 回调或 Promise 处理程序将运行。