1

为了深入了解有关 Node.js 的更复杂的概念,我正在做一些研究以确保我了解有关该语言的原理及其构建的基本构建块。

就我而言,Node.js 依赖于反应器模式来处理每个传入的请求。该算法基于事件解复用器算法。第二个负责处理请求操作及其资源,然后,一旦操作完成,它将“结果”添加到事件队列中。在这个过程之后,事件循环现在负责为每个事件执行处理程序。

作为一个单线程进程,如果事件循环并行管理所有事件队列任务,我正在努力理解事件多路分解器如何处理所有传入操作......

我在Node.js 文档中找到了这个:

由于大多数现代内核都是多线程的,它们可以处理在后台执行的多个操作。当这些操作之一完成时,内核会通知 Node.js,以便可以将适当的回调添加到轮询队列中以最终执行。我们将在本主题后面更详细地解释这一点。

这是否意味着 Node 不处理 Event Demultiplexer 任务并且 Node 只是获取结果以便将其添加到事件队列中?这是否意味着 Node 不是单线程的?

我在网上找到了一些有用的图形,它们清楚地解释了每个请求所遵循的路径,但是真的很难找到一些解释线程处理每个请求的实际时间的图形。

4

1 回答 1

1

在 node.js 中,它在单个线程中运行您的 Javascript(假设我们不是在谈论工作线程或集群)。但是,node.js 内置库中的许多异步操作(例如文件 I/O 或一些加密操作)使用它们自己的线程来完成它们的任务。因此,当您调用异步操作(例如fs.open()打开文件)时,它会转换为本地代码,从内部线程池中获取一个线程,然后该线程开始打开文件。这fs.open()然后函数返回到您的Javascript(而线程在后台继续)。稍后,当它完成任务时,内部线程将一个事件插入到 nodejs 事件队列中,当 nodejs 有循环检查事件队列时,它会找到该事件并运行与之关联的 Javascript 回调以将异步结果返回给你的 Javascript。

因此,即使可能涉及线程,您的 Javascript 仍然是通过事件循环的单线程。

因此,nodejs 确实使用原生代码线程进行一些内部原生代码操作。网络和计时器等其他东西是在没有线程的情况下实现的。

那么如果我在 Node 中发送一个从数据库中获取数据的请求,Event Demultiplexer 是如何处理它的呢?主线程是否停止事件循环以处理该操作,然后在事件处理程序排队后恢复?

这些术语如“事件多路复用器”是您应用于 node.js 的东西。它们根本不是 node.js 使用的东西,所以我不完全确定你在问什么。

Node.js 一次运行一个事件。它没有中断驱动的能力。因此,它会运行一个事件,直到该事件将控制权返回给事件循环(通过return从启动一切的回调中发出 a )。现在,原始事件可能不完整——它可能正在做一些异步的事情,会触发另一个事件来宣布完成,但它现在已经完成了 Javascript 的运行并将控制权返回给事件循环。

当传入的 Fetch 请求(只是传入的 http 请求)到达服务器时,它首先由操作系统排队。然后,当事件循环有机会看到它时,它会被添加到 node.js 事件队列中,并在它之前的其他事件完成处理时以 FIFO 顺序提供服务。现在,nodejs 事件循环并不像单个事件队列那么简单。它实际上有几个不同的队列用于不同类型的工作,并且对首先运行的内容具有优先级,但在最简单的级别上,您可以开始将其视为单个 FIFO 队列。而且,没有任何事情被打断。

从事件队列中拉出一个事件,运行与之关联的 Javascript 回调。当该回调返回事件循环时,获取下一个事件并执行相同操作。

事件可以通过本机代码线程(例如可能通过文件 I/O 或某些加密操作完成)或通过作为事件循环周期的一部分内置在事件循环中的某些轮询机制添加到事件队列中,它会检查某些事情准备好运行(与网络和计时器一样)。

于 2020-09-16T15:53:43.343 回答