写点什么

深入解析 Node.js 事件循环工作机制

  • 2019-08-06
  • 本文字数:2689 字

    阅读完需:约 9 分钟

深入解析Node.js事件循环工作机制

本文从对线程、事件循环、事件循环常见的问题和错误上分别进行说明,进一步探索了 Node 的核心工作原理。


每当人们谈论 Node.js 时,都会出现很多问题,比如它究竟是什么、这项技术有什么用、它是否有未来等等。


让我们尝试讨论第一部分。回答这个问题最简单的方法是列出 Node 在技术上的许多定义,如:


  • Node.js 是一个基于 Chrome V8 JavaScript 引擎构建的 Javascript 运行时环境。

  • Node.js 使用事件驱动的非阻塞 I/O 模型,这使其轻量且高效。

  • Node 包生态系统(npm)是全世界最大的开源库生态系统。


但是,这些答案并不能令我完全满意,因为缺少有些东西。在阅读上面的要点后,你可能会认为 Node.js 只是另一种 JavaScript 技术,但理解它最重要的方法是分析它是如何实现异步并具有完全非阻塞 I/O 系统的。


这才是为什么它能成为每个 Web 开发人员必备之物的真正原因。


准确了解 Node 如何在幕后工作不仅能增进对这项技术的更多了解,而且还会吸引那些还未用过它的人认识并开始学习它。


而对于那些已经是该领域专业人士的人来说,了解 Node 的内部和外部将使你成为一名最新和最前沿的开发人员,并且能够根据自身的需求提高 Node 的性能。


因此,为了挖掘 Node 的世界,我们将检查其核心的部分:事件循环,事实上,事件循环就是负责 Node 非阻塞 I/O 模型的部分。

对线程认识的简要刷新

在深入了解事件循环之前,我想花些时间在线程上。如果你想知道为什么这很必要,我会告诉你,为了更好地理解一个概念,我们必须首先开始在脑海中形成一个词汇表,它将有助于我们识别系统的每个部分。这样,在稍后阅读有关事件循环、事件循环如何工作以及线程的概念如何应用在事件循环中的内容时,你才会有很大的优势。


每当我们运行一个程序时,我们都会创建一个它的实例,并且我们会调用一些内部线程,他们是与该实例相关联的。线程可以看作是 CPU 必须执行的操作单元。许多不同的线程可以与程序的单个进程相关联。以下是一个图形,它可以帮助你在脑海中形成这个概念:



线程的简单图形


在谈论线程时,最重要的一点是:机器如何确定在某个时刻处理哪个线程?


众所周知,我们的机器资源(CPU、RAM)是有限的,因此正确确定我们将资源分配在哪里非常重要,或者说,哪些操作应该优先于其他操作。这一切都必须实现,而且同时,需要确保没有任何操作耗费太多时间,因为没有人喜欢笔记本电脑速度过慢。


用于解决资源分配问题的机制就叫作调度,它由我们的操作系统中称为 OS 调度程序的实体来管理。这背后的逻辑可能非常复杂,但总而言之,我们可以将执行此操作的两大方法组合在一起:




多核机器如何处理线程


  • 使用优化逻辑,以减少死锁时间:这是对我们来说最切实的方法。如果我们仔细研究一下线程是如何工作的,我们就会看到 OS 调度程序可以识别出 CPU 何时在等待其他资源来执行某个作业,以便分配这个资源来同时执行其他操作。这通常发生在非常昂贵的 I/O 操作上,例如硬盘读取。

事件循环

现在我们已经对线程的工作原理有了新的了解,我们终于可以解决 Node.js 事件循环逻辑了。通过阅读本文,你会了解前面的解释它背后的原因,而且每个部分都会自行找到正确的位置。


每当我们运行 Node 程序时,都会自动创建一个线程。这个线程就是我们整个代码库被执行的唯一地方。其中,还生成了一个称为事件循环的东西。这个循环的作用是安排我们唯一的线程在某个给定的时间点应该执行哪些操作。


请注意:在我们运行了程序后那一刹那,事件循环不会立刻生成。实际上,只有在整个程序执行完毕后事件循环才会运行。

详情

现在让我们尝试模拟事件循环的工作原理以及它如何使我们的程序开始工作。为此,我将假装自己正在使用一个名为 myProgram 的文件为 Node 提供信息,然后我们再详细了解事件循环将执行的所有操作。



特别的,我将首先编写一个简短的图形解释,来说明在某个事件循环 tick 过程中发生了什么,然后我将以更深入的方式探讨这些阶段。



事件循环的图形说明

第 1 步:performChecks

我不应该告诉你事件循环实际上是一个循环。这意味着它有一个特定的条件,这个条件将决定循环是否需要再次迭代。事件循环的每次迭代都称为 tick


事件循环执行 tick 的条件是什么?


每当我们执行程序时,我们都会有一系列需要执行的操作。这些操作可分为三个大类:


  • 挂起的定时器操作 (setTimeout(), setInterval(),setImmediate())

  • 挂起的操作系统(OS)任务

  • 挂起的长时间运行操作的执行


我们稍后会详细介绍这些内容;现在,让我们记住,只要其中一个操作处于挂起状态,事件循环就会执行一个新的 tick。

第 2 步:执行 tick

对于每个循环迭代,我们可以将其分为以下阶段:


  • 阶段 1:Node 查看挂起的计时器的内部集合,并检查传递给setTimeout()setInterval()的回调函数是否准备好在计时器过期的情况下被调用。

  • 阶段 2:Node 查看挂起的 OS 任务的内部集合,并检查哪些回调函数已准备好被调用。从机器的硬盘驱动器中检索文件即是一个例子。

  • 阶段 3:Node 暂停执行,等待新事件的出现。新事件包括:新的计时器完成、新的 OS 任务完成和新的挂起操作完成。

  • 阶段 4:Node 检查是否准备好调用与挂起定时器(挂起定时器与setImmediate()函数相关)相关的任何函数。

  • 阶段 5:管理关闭事件,用于清理应用程序的状态。

关于事件循环的常见问题和错误认识

Node.js 是完全单线程的吗?

这是对这项技术的一种非常普遍的误解。虽然 Node 是在单个线程上运行,但是 Node.js 标准库中包含的有些函数并不是如此(例如 fs 模块函数);它们的逻辑运行在 Node.js 单线程之外,这样做是为了保持程序的速度和性能。

这些其他线程在哪里外包?

使用 Node.js 时,会使用一个名为 libuv 的特殊库模块来执行异步操作。此库还与 Node 的后向逻辑一起被用来管理称为 libuv 线程池的特殊线程池。


此线程池由四个线程组成,它们负责委派对事件循环来说太繁重的操作。上述事件循环逻辑中的长时间运行的任务代表此处所描述的对于事件循环而言过于昂贵的操作。

那么事件循环是一种类似堆栈的结构吗?

从这个意义上说,虽然在上述过程中涉及到了一些类似堆栈的结构,但更准确的答案是事件循环由一系列阶段组成,每个阶段都有自己的特定任务,而且所有阶段都以循环重复的方式被处理。有关事件循环确切结构的更多信息,请看这个对话

结论

了解事件循环是使用 Node.js 的重要部分,无论你是想获得有关此技术的更多见解、了解如何提高其性能,还是希望找到学习一个新工具的新的且有趣的理由。


本指南应当能帮助你探索这个主题。请在下面发表评论,你的意见和反馈将有助于每个人更好地学习。


英文原文:https://blog.logrocket.com/a-complete-guide-to-the-node-js-event-loop/


2019-08-06 10:062616
用户头像

发布了 34 篇内容, 共 19.8 次阅读, 收获喜欢 47 次。

关注

评论

发布
暂无评论
发现更多内容

QCA9880 wallys 2×2 MIMO 802.11ac Mini PCIe 2,4GHz / 5GHz Designed for E

wallys-wifi6

QCA9882 wallys 802.11AC 802.11AN wifi QCA9882 Module Wireless AC/AN MiniPCIE Standard Card

wallys-wifi6

QCA9882

TiFlash 源码阅读(六)DeltaTree Index 的设计和实现分析

PingCAP

TiDB TiDB 源码解读

数据结构——二叉树

工程师日月

8月月更

开源的价值观与文化的传递

开源社

#开源

我和谷歌共成长——我的Google Play上车之路

云村的泊

8月月更

阿里最新的Spring Boot项目开发实战手册,掀起了项目实战变革狂潮

Java面试那些事儿

Java 编程 程序员 面试 架构师

Node 之父着急宣布Deno 将迎来重大变革,疑为针对最近大火的“Bun”

雨果

node.js

OpenHarmony轻量设备Hi3861芯片开发板启动流程分析

OpenHarmony开发者

OpenHarmony

开源一夏 | 在 STM32L051 上使用 RT-Thread (二、无线温湿度传感器 之 CubeMX配置)

矜辰所致

开源 RT-Thread 8月月更 STM32L051

国产系统的不足或许可以靠小程序弥补

Geek_99967b

小程序

微服务、网关、服务发现/注册的正确打开方式

Java全栈架构师

Java 程序员 架构 微服务 程序人生

融会贯通,并行不悖 | 2022年8月《中国数据库行业分析报告》精彩抢先看

墨天轮

数据库 greenplum MPP 国产数据库 HTAP

泄露了,22年阿里巴巴秋招内部面试资料,看完之后剑指offer

Java面试那些事儿

Java 编程 程序员 面试 架构师

美国商务部宣布:EDA等四项技术实施新的出口管制,8月15日生效!

雨果

芯片技术

区块链带你避“坑”,电信诈骗退!退!退!

旺链科技

区块链 产业区块链 电信诈骗

Solana上的结算协议龙头,Zebec潜力颇受看好

小哈区块

4步教你学会使用Linux-Audit工具

华为云开发者联盟

Linux 工具 安全 监控 开发

一文搞定架构思维,DFD 的结构化分析,只需明白这3点

老崔说架构

量化交易合约机器人系统开发策略分析

薇電13242772558

量化策略

10种有用的Linux Bash_Completion 命令示例

华为云开发者联盟

Linux 后端 开发

如何在企业数字化团队内部实现分析建模过程全要素的可获得与成果可复现

ModelWhale

团队协作 数字化转型 全要素场景 代码复现 金融场景

C#/VB.NET 替换 PDF 文件上的现有图像

在下毛毛雨

C# .net PDF 替换图像

数据工程师越做越有成就感的7点经验分享

雨果

数据工程师

JSON 之父:JavaScript 已经成为了进步的障碍

雨果

JavaScript

Linux 6.0 第一个候选版本发布

雨果

Liunx

乔布斯之后,下一代触控交互由一家中国公司重新定义

硬科技星球

怎么分辨企业转型是“真数字化”还是 “伪数字化”?

雨果

数字化转型

泄露了,Alibaba697页的MySQL应用实战与性能调优手册,太强了

Java编程日记

Java 编程 程序员 面试 架构师

从入门到高手,数据从业者成长一般经过哪些阶段?

雨果

数据工程师必备技能

深入解析Node.js事件循环工作机制_语言 & 开发_Piero Borrelli_InfoQ精选文章