菜单

核心架构

相关源文件

本文档描述了 Node.js 的高层架构,重点关注其核心组件以及它们如何交互。它概述了构成 Node.js 的主要系统、它们的职责以及它们之间的关系。有关特定组件的更详细信息,请参阅相应的页面,例如 V8 集成环境和启动过程工作线程架构模块系统

核心组件概述

Node.js 构建于几个关键组件之上,这些组件协同工作以提供其运行时环境。

来源

Node.js 通过 C++ 绑定层将 V8 JavaScript 引擎与平台无关的异步 I/O 库 (libuv) 结合起来。这使得 JavaScript 能够以非阻塞方式与文件系统、网络和定时器等系统资源进行交互。

Node.js 进程初始化

Node.js 的启动过程涉及几个关键步骤来设置运行时环境。

来源

初始化过程涉及几个关键步骤:

  1. 处理命令行参数和环境变量
  2. 设置 V8 平台并创建 Isolate
  3. 创建 IsolateData 和 Environment
  4. 初始化 libuv handle 以实现事件驱动的 I/O
  5. 运行引导代码以设置 JavaScript 环境
  6. 执行主入口模块或 REPL

核心架构组件

IsolateData 和 Environment 类

来源

Node.js 使用两个关键类来管理其运行时状态:

  1. IsolateData:包含同一 V8 Isolate 中多个环境共享的数据,包括:

    • 对 V8 Isolate 的引用
    • libuv 事件循环
    • V8 平台
    • 用于提高性能的模板缓存
    • 每个 Isolate 的字符串和符号属性
  2. Environment:代表一个完整的 JavaScript 执行上下文,具有自己的:

    • 全局对象和上下文
    • 事件循环状态
    • 回调队列
    • 内置模块
    • 通过 AsyncHooks 跟踪异步资源
    • 通过 ImmediateInfoTickInfo 进行定时器和立即回调

每个 Node.js 进程至少有一个主 Environment 实例。工作线程和其他隔离上下文可能存在其他 Environment 实例。

事件循环集成

Node.js 将 libuv 事件循环与 V8 的执行模型集成。

来源

事件循环是 Node.js 非阻塞 I/O 模型的核心。

  1. Node.js 使用各种 handle 集成到 libuv 的事件循环中:

    • uv_timer_t 用于定时器 (setTimeout/setInterval)
    • uv_check_t 用于立即回调 (setImmediate)
    • 各种 I/O handle,用于文件系统、网络等。
  2. process.nextTick() 不使用 libuv 事件循环,但在 libuv 阶段之间处理。

  3. Promise 微任务在 V8 中每个“微任务检查点”之后处理。

内存管理与 V8 集成

Node.js 通过与 V8 的集成来仔细管理内存。

组件职责
NodeArrayBufferAllocator用于 ArrayBuffer 的自定义分配器
DebuggingArrayBufferAllocator用于跟踪内存分配的调试版本
SetIsolateCreateParamsForNode根据可用内存配置 V8 堆大小
SetIsolateUpForNode设置用于错误处理、Promise 拒绝等的 callback
AsyncWrap跟踪异步资源以进行调试和性能分析
HandleWrap所有 libuv handle 包装器的基类

来源

内存管理包括:

  1. 用于跟踪 JavaScript 内存使用情况的自定义 ArrayBuffer 分配器
  2. 根据可用系统内存配置 V8 堆大小
  3. 管理 libuv handle 的生命周期以防止内存泄漏
  4. 与 V8 的垃圾回收器集成以进行正确的资源清理

进程标志和配置

Node.js 的行为可以通过各种编译和运行时标志来控制。

来源

Node.js 提供了广泛的配置选项:

  1. ProcessGlobalArgs 解析的命令行参数
  2. 环境变量,包括 NODE_OPTIONS
  3. 控制启动各种方面的进程初始化标志
  4. 用于调整 JavaScript 引擎的 V8 标志
  5. 用于持久化配置的配置文件

快照系统

Node.js 包含一个快照系统以提高启动性能。

来源

快照系统

  1. 捕获 V8 堆、内置代码缓存和 Node.js 环境的状态
  2. 将此数据序列化为二进制 blob
  3. 在启动时反序列化以跳过初始化步骤
  4. 通过避免 JavaScript 解析和编译,显著提高启动时间
  5. 支持内置快照和用户创建的自定义快照

工作线程架构

Node.js 通过 Worker Threads API 支持多线程。

来源

Node.js 中的工作线程

  1. 拥有自己的 V8 Isolate、上下文和 libuv 事件循环
  2. 通过消息端口与主线程通信
  3. 可以应用资源约束(内存限制等)
  4. 通过 SharedArrayBuffer 与主线程共享某些数据
  5. 使用线程安全的线程间通信进行大部分通信

引导过程

Node.js 使用复杂的引导过程来设置其 JavaScript 环境。

阶段入口点描述
1. 平台设置node.cc main设置 V8 平台并处理参数
2. Isolate 创建NewIsolate()创建并初始化 V8 Isolate
3. Environment 创建CreateEnvironment()创建 Node.js 环境和上下文
4. Node.js 引导StartExecution()运行引导 JavaScript 代码
5. Context 初始化internal/bootstrap/node.js设置全局对象和核心模块
6. 入口点选择StartExecution()选择主脚本或 REPL 执行

来源

引导过程连接了 C++ 和 JavaScript 功能。

  1. 设置 V8 环境并为 JavaScript 执行做准备
  2. 从内部源加载内置 JavaScript 模块
  3. 使用 Node.js 特定的属性初始化全局对象
  4. 准备模块加载系统(CommonJS 和 ESM)
  5. 根据命令行参数确定入口点

Builtins 和模块加载

Node.js 包含丰富的内置模块集。

来源

Node.js 内置模块系统

  1. 将 JavaScript 模块预编译到二进制文件或从磁盘加载
  2. 缓存已编译的代码以供将来更快地加载
  3. 对可以直接被用户代码或不能直接被用户代码使用的模块进行分类
  4. 为 Node.js 功能提供内部 JavaScript 模块
  5. 同时作为 CommonJS 和 ESM 模块系统的基础

关键架构概念概述

Node.js 核心架构提供了几项重要功能

  1. 绑定层:C++ 代码通过 V8 将系统功能暴露给 JavaScript
  2. 事件循环集成:libuv 为非阻塞 I/O 提供了一个平台无关的事件循环
  3. 工作线程:支持并行 JavaScript 执行,并带有隔离和消息传递
  4. 启动优化:快照系统通过预编译代码来提高启动时间
  5. 模块系统:支持 CommonJS 和 ECMAScript 模块
  6. 跨平台抽象:跨操作系统的一致 API

该架构使 JavaScript 代码能够高效地与操作系统资源进行交互,同时保持 Node.js 所熟知的异步、事件驱动的编程模型。