Node.js 架构全景
Node.js 是基于 V8 引擎的 JavaScript 运行时,通过 libuv 实现非阻塞 I/O,适合构建高并发的网络应用。
架构组成
┌─────────────────────────────────────────────┐
│ Node.js Application │
├─────────────────────────────────────────────┤
│ Node.js Core Modules │
│ (fs, http, stream, crypto, path...) │
├─────────────────────────────────────────────┤
│ Node.js Bindings │
├──────────────────┬──────────────────────────┤
│ V8 Engine │ libuv │
│ (JS 执行引擎) │ (事件循环 + 异步 I/O) │
├──────────────────┴──────────────────────────┤
│ 操作系统 │
└─────────────────────────────────────────────┘libuv 事件循环
Node.js 事件循环的 6 个阶段:
┌─────────────────────────────┐
│ 1. timers │ ← setTimeout / setInterval 回调
│ 2. pending callbacks │ ← 上一轮延迟的 I/O 回调
│ 3. idle, prepare │ ← 内部使用
│ 4. poll │ ← 获取新 I/O 事件(核心阶段)
│ 5. check │ ← setImmediate 回调
│ 6. close callbacks │ ← socket.on('close') 等
└─────────────────────────────┘
每个阶段之间:清空 nextTick 队列 + 微任务队列
poll 阶段:
- 如果有 I/O 回调 → 执行
- 如果没有 → 等待新 I/O 事件(阻塞,直到有定时器到期)模块系统
js
// CommonJS(Node.js 传统)
const fs = require('fs')
const { join } = require('path')
module.exports = { myFunction }
// ESM(现代,推荐)
import fs from 'fs'
import { join } from 'path'
export { myFunction }
export default class MyClass {}
// package.json 配置
{
"type": "module" // 启用 ESM
}
// 条件导出(同时支持 CJS 和 ESM)
{
"exports": {
".": {
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
}
}
}核心模块速览
js
import fs from 'fs/promises'
import path from 'path'
import { createServer } from 'http'
import { EventEmitter } from 'events'
import { Worker } from 'worker_threads'
import { createReadStream, createWriteStream } from 'fs'
import { pipeline } from 'stream/promises'
import crypto from 'crypto'
import os from 'os'
// fs/promises:文件操作
const content = await fs.readFile('file.txt', 'utf-8')
await fs.writeFile('output.txt', content)
const files = await fs.readdir('./src')
const stat = await fs.stat('file.txt')
// path:路径处理
const fullPath = path.join(__dirname, 'src', 'index.ts')
const ext = path.extname('file.ts') // '.ts'
const dir = path.dirname('/foo/bar/baz.js') // '/foo/bar'
const { name, ext: extension } = path.parse('file.ts')
// crypto:加密
const hash = crypto.createHash('sha256').update('data').digest('hex')
const salt = crypto.randomBytes(16).toString('hex')
// os:系统信息
const cpuCount = os.cpus().length
const totalMem = os.totalmem()
const freeMem = os.freemem()Stream 流处理
js
import { pipeline } from 'stream/promises'
import { createReadStream, createWriteStream } from 'fs'
import { createGzip } from 'zlib'
import { Transform } from 'stream'
// 管道:读取 → 压缩 → 写入(内存高效)
await pipeline(
createReadStream('input.txt'),
createGzip(),
createWriteStream('output.txt.gz')
)
// 自定义 Transform 流
const upperCase = new Transform({
transform(chunk, encoding, callback) {
callback(null, chunk.toString().toUpperCase())
}
})
// 处理大文件(逐行读取)
import readline from 'readline'
const rl = readline.createInterface({
input: createReadStream('large-file.csv'),
crlfDelay: Infinity
})
for await (const line of rl) {
processLine(line) // 逐行处理,不占用大量内存
}Worker Threads(CPU 密集型任务)
js
// main.js
import { Worker, isMainThread, parentPort, workerData } from 'worker_threads'
if (isMainThread) {
// 主线程:创建 Worker
function runWorker(data) {
return new Promise((resolve, reject) => {
const worker = new Worker(new URL(import.meta.url), {
workerData: data
})
worker.on('message', resolve)
worker.on('error', reject)
})
}
// 并行执行 CPU 密集型任务
const results = await Promise.all([
runWorker({ start: 0, end: 1000000 }),
runWorker({ start: 1000000, end: 2000000 }),
runWorker({ start: 2000000, end: 3000000 }),
runWorker({ start: 3000000, end: 4000000 }),
])
console.log('总和:', results.reduce((a, b) => a + b, 0))
} else {
// Worker 线程:执行计算
const { start, end } = workerData
let sum = 0
for (let i = start; i < end; i++) sum += i
parentPort.postMessage(sum)
}性能最佳实践
js
// 1. 避免阻塞事件循环
// ❌ 同步读取大文件
const data = fs.readFileSync('large-file.txt')
// ✅ 异步读取
const data = await fs.readFile('large-file.txt')
// 2. 连接池(数据库)
import { Pool } from 'pg'
const pool = new Pool({ max: 20 }) // 复用连接,不要每次请求都创建新连接
// 3. 内存泄漏检测
process.on('warning', (warning) => {
if (warning.name === 'MaxListenersExceededWarning') {
console.error('可能存在内存泄漏:', warning)
}
})
// 4. 优雅关闭
process.on('SIGTERM', async () => {
console.log('收到 SIGTERM,开始优雅关闭...')
await server.close()
await db.end()
process.exit(0)
})总结
- Node.js 单线程 + 非阻塞 I/O,适合 I/O 密集型,不适合 CPU 密集型
- CPU 密集型任务用 Worker Threads 或子进程
- Stream 处理大文件,避免一次性加载到内存
- 生产环境用 PM2 或 Docker 管理进程,配置优雅关闭