Appearance
Node.js 核心机制
线程池 · 集群 · 工作线程 · EventEmitter · V8 引擎 · Reactor 模式 · 中间件
一、核心机制
1. 线程池(libuv)
线程池由 libuv 库处理。libuv 是一个多平台 C 库,它支持基于异步 I/O 的操作,例如文件系统、网络和并发。
2. 集群模式
- Node.js 应用程序在单个处理器上运行,默认情况下不会利用多核系统
- 集群模式用于启动多个 node.js 进程,从而拥有多个事件循环实例
- 使用集群时,会创建多个 node.js 进程,还有一个称为集群管理器的父进程,负责监控各个实例的健康状况
3. 工作线程 vs 集群
Cluster 簇
| 特点 | 说明 |
|---|---|
| 进程模型 | 每个 CPU 上都有一个进程,通过 IPC 通信 |
| 适用场景 | 多个服务器通过单个端口接受 HTTP 请求 |
| 内存 | 每个 CPU 中产生独立进程,具有单独的内存和节点实例 |
Worker Threads 工作线程
| 特点 | 说明 |
|---|---|
| 进程模型 | 总共只有一个进程,有多个线程 |
| 每个线程 | 拥有一个 Node 实例(一个事件循环,一个 JS 引擎) |
| 内存 | 与其他线程共享内存(如 SharedArrayBuffer) |
| 适用场景 | CPU 密集型任务(数据处理、文件系统等) |
4. 事件发射器(EventEmitter)
EventEmitter 是一个 Node.js 类,包含所有能够发出事件的对象。
- 通过
eventEmitter.on()函数附加命名事件 - 当对象抛出事件时,附加的函数会被同步调用
js
const EventEmitter = require('events');
const myEmitter = new EventEmitter();
myEmitter.on('myEvent', () => {
console.log('事件被触发');
});
myEmitter.emit('myEvent');5. Performance API
Performance API 提供了性能指标工具,结合 async_hooks 和 perf_hooks:
js
const { performance, PerformanceObserver } = require('perf_hooks');
const obs = new PerformanceObserver((items) => {
console.log(items.getEntries()[0].duration);
performance.clearMarks();
});
obs.observe({ entryTypes: ['measure'] });
performance.mark('A-start');
// 异步操作
performance.mark('A-end');
performance.measure('A', 'A-start', 'A-end');二、V8 引擎与架构
6. 为什么 Google 使用 V8 引擎?
V8 是 Google 开发的 JavaScript 引擎,选择原因:
- 发展最快,性能优化持续改进
- 其他选择:Firefox 的 SpiderMonkey、Edge 的 Chakra
7. Express 应用与服务器分离
| 职责 | 说明 |
|---|---|
| 服务器 | 负责初始化路由、中间件和其他应用程序逻辑 |
| 应用程序 | 包含所有业务逻辑,由服务器启动的路由提供服务 |
好处:业务逻辑被封装并与应用程序逻辑解耦,项目更具可读性和可维护性
js
// app.js - 应用程序
const express = require('express');
const app = express();
app.get('/', (req, res) => { res.send('Hello World'); });
module.exports = app;
// server.js - 服务器
const app = require('./app');
const http = require('http');
const server = http.createServer(app);
server.listen(3000);8. Reactor 反应器模式
Reactor 模式用于非阻塞 I/O 操作的事件驱动架构。
| 组件 | 职责 |
|---|---|
| Reactor | 将 I/O 事件分派给适当的处理程序 |
| Handler | 实际处理这些事件 |
9. 中间件
中间件介于请求和业务逻辑之间。
主要用途:捕获日志、启用速率限制、路由、身份验证、任何不属于业务逻辑的部分
类型:第三方中间件(如 body-parser)、自定义中间件
js
app.use((req, res, next) => {
console.log(`${req.method} ${req.url}`);
next();
});前端框架中间件机制(Axios/Vuex/Redux/Koa)详见 框架 · 状态管理与中间件