【问题标题】:What is the difference between single thread and non-blocking I/O operation in NodeJs?NodeJs 中的单线程和非阻塞 I/O 操作有什么区别?
【发布时间】:2013-05-31 11:27:36
【问题描述】:

我一直在阅读和阅读尽可能多的 NodeJs 代码,但我对此有点困惑:

Node 是单线程究竟是什么意思,非阻塞 I/O 是什么意思?我可以通过产生一个子进程和第二个通过使用异步库来实现第一个。但我想弄清楚它的含义以及非阻塞 I/O 如何仍然会减慢您的应用程序。

【问题讨论】:

标签: node.js


【解决方案1】:

我会尽力解释的。

单线程意味着 Node.js Javascript 运行时 - 在特定时间点 - 仅从它已加载的所有代码中执行一段代码。实际上,它从某个地方开始,并通过所有指令(调用堆栈)向下运行,直到完成。当它在执行代码时,没有任何东西可以中断这个过程,所有的 I/O 都必须等待。值得庆幸的是,大多数调用堆栈都相对较短,而且我们在 Node.js 中做的很多事情更多的是“簿记”类型,而不是 CPU 密集型。

虽然是单线程,但任何需要很长时间的指令都会对系统的响应能力造成巨大的问题。运行时一次只能做一件事,所以一切都必须等到该指令完成。如果任何“I/O”指令(比如从磁盘读取)会阻塞执行,那么系统将在那时不必要地不可用。

但幸运的是,我们有非阻塞 I/O。

而不是等待读取文件:

console.log(readFileSync(filePath))

您编写代码,这样您就不必等待读取文件:

readFile(filePath)

readFile 调用几乎立即返回(可能在几纳秒内),因此运行时可以继续执行接下来的指令。但是如果 readFile 调用在数据被读取之前返回,那么 readFile 调用就无法返回文件内容。这就是回调的用武之地:

readFile(filePath, function(err, contents) { console.log(contents))

不过,readFile 调用几乎立即返回。运行时可以继续。它将完成之前的当前工作(所有指令都在 readFile 之后)。除了存储对它的引用之外,没有对传递的函数做任何事情。

然后,在稍后的某个时间点(可能是 10 毫秒、100 毫秒或 1000 毫秒之后),当读取文件完成时,将使用文件的完整内容作为第二个参数调用回调。在此之前,运行时可以完成任何数量的其他工作。

现在我将向您的 cmets 介绍如何生成子进程和异步库。你在这两个方面都错了。

  • 生成子进程是让 Node.js 使用更多 CPU 内核的方法。作为单线程,单个 Node.js 没有使用多个内核的目的。不过,如果您使用的是多核计算机,您可能希望使用所有这些内核。因此,启动多个 Node.js。进程。

  • Async 库不会为您提供非阻塞 I/O,Node.js 为您提供。 Node.js 本身并没有给您提供一种处理来自多个回调的数据的简单方法。 Async 库可以帮助解决这个问题。

由于我不是 Node.js 内部的专家,欢迎指正!

相关问题:

【讨论】:

  • 优秀的答案,我显然在很多方面都错了。那么你认为如何处理 CPU 密集型任务呢?比如,假设我有一个可以同步来自各个网站的信息的应用程序。同步可以作为后台进程以定期轮询的方式发生。您不建议为此使用衍生进程吗?
  • 当然不是。由于轮询是周期性的,并且每次轮询后需要完成的实际工作(即计算)可能很小,因此它是单个 Node.js 进程的绝佳用例。使用多个进程的唯一原因是您希望能够使多个内核饱和。
  • 我构建轮询的想法是编写一个单独的看门狗类库,它在单独的线程上运行并不断轮询和更新数据库,而不会打扰事件循环/用户请求。
  • 您可以在单个 Node.js 进程中执行此操作。 Node.js 甚至没有阻塞 HTTP 功能,所以你要做的任何事情都必须是非阻塞的。处理异步编程风格比处理 Node 的性能更麻烦。
猜你喜欢
  • 1970-01-01
  • 2019-09-24
  • 1970-01-01
  • 2022-07-25
  • 2022-01-09
  • 2012-02-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多