node.js - 什么时候使用线程池?

标签 node.js events

所以我对 Node.js 的工作原理有所了解:它有一个监听器线程,用于接收事件,然后将其委托(delegate)给工作池。工作线程完成工作后通知监听器,然后监听器将响应返回给调用者。

我的问题是:如果我在 Node.js 中建立一个 HTTP 服务器并在我的一个路由路径事件(例如“/test/sleep”)上调用 sleep,整个系统就会停止。甚至是单个监听器线程。但我的理解是这段代码发生在工作池上。

相比之下,当我使用 Mongoose 与 MongoDB 通信时,DB 读取是一项昂贵的 I/O 操作。 Node 似乎能够将工作委托(delegate)给一个线程,并在它完成时接收回调;从数据库加载所花费的时间似乎并没有阻塞系统。

Node.js 如何决定使用线程池线程与监听器线程?为什么我不能编写休眠并且只阻塞线程池线程的事件代码?

最佳答案

您对 Node 如何工作的理解不正确......但这是一个常见的误解,因为实际情况实际上相当复杂,通常可以归结为“Node 是单线程的”之类的简洁的小短语。 - 简化事情。

目前,我们将通过 cluster 忽略显式的多处理/多线程。和 webworker-threads , 就说说典型的非线程 Node 吧。

Node 在单个事件循环中运行。它是单线程的,你只能得到一个线程。您编写的所有 javascript 都在此循环中执行,如果在该代码中发生阻塞操作,那么它将阻塞整个循环,并且在它完成之前不会发生任何其他事情。这是您经常听到的 Node 的典型单线程特性。但是,这不是全部。

某些函数和模块,通常用 C/C++ 编写,支持异步 I/O。当您调用这些函数和方法时,它们会在内部管理将调用传递给工作线程。例如,当您使用 fs 模块请求文件时,fs 模块将该调用传递给一个工作线程,该工作线程等待它的响应,它然后呈现回在没有它的情况下一直在搅动的事件循环。所有这些都从您, Node 开发人员那里抽象出来,其中一些是通过使用 libuv 从模块开发人员那里抽象出来的。 .

正如 Denis Dollfus 在评论中指出的(从 this answer 到类似的问题),libuv 用于实现异步 I/O 的策略并不总是线程池,特别是在 的情况下http 模块此时似乎使用了不同的策略。出于我们的目的,重要的是要注意异步上下文是如何实现的(通过使用 libuv),以及 libuv 维护的线程池是该库提供的用于实现异步的多种策略之一。


在一个最相关的切线上,对 Node 如何实现异步性以及一些相关的潜在问题以及如何处理它们进行了更深入的分析,in this excellent article .大部分内容都扩展了我上面写的内容,但另外指出:

  • 项目中包含的任何使用原生 C++ 和 libuv 的外部模块都可能使用线程池(想想:数据库访问)
  • libuv 的默认线程池大小为 4,并使用队列来管理对线程池的访问 - 结果是,如果您同时有 5 个长时间运行的数据库查询,其中一个(和任何其他依赖于线程池的异步操作)将在这些查询开始之前等待它们完成
  • 您可以通过 UV_THREADPOOL_SIZE 环境变量增加线程池的大小来缓解这种情况,只要您在需要和创建线程池之前执行此操作:process.env。 UV_THREADPOOL_SIZE = 10;

如果你想在node中进行传统的多处理或多线程,你可以通过内置的cluster模块或其他各种模块如前面提到的webworker-threads,或者您可以通过实现某种方式将您的工作分 block 并手动使用 setTimeoutsetImmediateprocess.nextTick 来暂停您的工作并在以后的循环中继续它以让其他流程完成(但不建议这样做)。

请注意,如果您在 javascript 中编写长时间运行/阻塞的代码,您可能会犯错误。其他语言的执行效率会更高。

关于node.js - 什么时候使用线程池?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22644328/

相关文章:

node.js - 如何使用 Nodemon 监控符号链接(symbolic link)模块?

javascript - Sequelize.js如何按多列划分的结果进行排序?

c# - 事件取消订阅/重新订阅属性更改

javascript - Koa-session 在附加对象后被重置?

node.js - 使用 Passport 授权时设置 Postman 进行 API 测试

javascript - 等待循环点击

javascript - 第一次点击不会触发事件

java - 如何有多个循环/进程/等。同时发生?

objective-c - Cocos2d - Mac : Check for keyboard events?

javascript - ESLint - 识别外部(CDN)库的方法