进程与线程概念
进程与线程的基本概念
进程是操作系统资源分配的基本单位,每个进程拥有独立的内存空间、文件描述符等系统资源。线程则是进程内的执行单元,共享进程的资源但拥有独立的执行栈和程序计数器。操作系统通过进程隔离保证程序稳定性,而线程则用于提高程序执行效率。
Node.js虽然是单线程模型,但通过事件循环和异步I/O实现了高并发。底层实际上仍依赖线程池处理部分任务,如文件I/O、DNS查询等。这种设计既避免了多线程编程的复杂性,又充分利用了多核CPU的优势。
// 查看Node.js进程信息
console.log(`进程PID: ${process.pid}`);
console.log(`内存使用: ${JSON.stringify(process.memoryUsage())}`);
Node.js中的进程模型
Node.js主进程运行V8引擎和事件循环,当启动应用时创建单个进程。这个主进程负责JavaScript代码执行、事件调度和请求响应。对于CPU密集型任务,Node.js提供了child_process模块创建子进程,典型场景包括:
- 图像/视频处理
- 大数据计算
- 机器学习推理
const { fork } = require('child_process');
const computeProcess = fork('./heavy-computation.js');
computeProcess.send({ data: largeDataSet });
computeProcess.on('message', result => {
console.log('计算结果:', result);
});
事件循环与线程池
Node.js通过libuv库实现事件循环机制,这个核心架构包含六个主要阶段:
- 定时器阶段(处理setTimeout/setInterval)
- 待定回调阶段(执行系统操作回调)
- 空闲/准备阶段(内部使用)
- 轮询阶段(检索新的I/O事件)
- 检查阶段(执行setImmediate回调)
- 关闭回调阶段(处理关闭事件)
底层线程池默认包含4个线程(可通过UV_THREADPOOL_SIZE环境变量调整),用于处理:
- 文件系统操作
- DNS解析
- 部分加密操作
- 所有Zlib异步操作
const fs = require('fs');
const crypto = require('crypto');
// 这些操作会使用线程池
fs.readFile('/large-file', (err, data) => {
crypto.pbkdf2('password', 'salt', 100000, 64, 'sha512', (err, key) => {
console.log(key.toString('hex'));
});
});
集群模式与进程通信
对于多核系统,Node.js提供了cluster模块实现多进程架构。主进程(master)可以fork多个工作进程(worker),这些进程共享服务器端口但运行独立的V8实例。进程间通信主要通过以下方式:
- IPC通道(child_process.fork()自动建立)
- 共享文件描述符
- 第三方消息队列(如Redis)
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
for (let i = 0; i < numCPUs; i++) {
const worker = cluster.fork();
worker.send('来自主进程的消息');
}
} else {
process.on('message', (msg) => {
console.log(`Worker ${process.pid} 收到: ${msg}`);
});
http.createServer((req, res) => {
res.end(`由Worker ${process.pid}处理`);
}).listen(8000);
}
Worker Threads模块详解
Node.js 10+引入了worker_threads模块,允许创建真正的多线程。与子进程不同,工作线程:
- 共享进程内存(通过SharedArrayBuffer)
- 启动开销更小
- 适合CPU密集型JavaScript操作
典型使用场景包括:
- 复杂数学计算
- JSON大数据处理
- 图像像素处理
const { Worker, isMainThread, parentPort } = require('worker_threads');
if (isMainThread) {
const worker = new Worker(__filename);
worker.on('message', msg => console.log('主线程收到:', msg));
worker.postMessage('ping');
} else {
parentPort.on('message', msg => {
console.log('工作线程收到:', msg);
parentPort.postMessage('pong');
});
}
内存管理与资源共享
多进程架构中内存不共享,每个进程有独立的堆内存。而工作线程可以通过以下方式共享数据:
- SharedArrayBuffer:真正的共享内存
- MessagePort:线程间通信通道
- Atomics API:共享内存的原子操作
const { Worker } = require('worker_threads');
const sharedBuffer = new SharedArrayBuffer(4);
const array = new Int32Array(sharedBuffer);
const worker = new Worker(`
const { parentPort, workerData } = require('worker_threads');
const array = new Int32Array(workerData);
Atomics.add(array, 0, 1);
parentPort.postMessage('done');
`, { workerData: sharedBuffer });
worker.on('message', () => {
console.log('共享数组值:', array[0]); // 输出1
});
错误处理与进程监控
多进程/线程环境需要特别注意错误处理:
- 子进程崩溃不会影响主进程
- 未捕获的线程异常会导致线程退出
- 需要实现进程守护机制
const { spawn } = require('child_process');
const child = spawn('node', ['worker.js']);
child.on('exit', (code, signal) => {
if (code !== 0) {
console.error(`子进程异常退出,代码${code}`);
// 实现自动重启逻辑
spawn('node', ['worker.js']);
}
});
process.on('uncaughtException', (err) => {
console.error('主进程未捕获异常:', err);
// 优雅退出
server.close(() => process.exit(1));
});
性能优化实践
根据应用类型选择合适的多任务方案:
- I/O密集型:单线程+异步I/O
- CPU密集型:工作线程或进程池
- 混合型:组合使用
// 线程池实现示例
const { Worker, isMainThread, parentPort, workerData } = require('worker_threads');
const os = require('os');
class ThreadPool {
constructor(script, size = os.cpus().length) {
this.workers = Array(size).fill().map(() => new Worker(script));
this.taskQueue = [];
this.workers.forEach(worker => {
worker.on('message', () => this.assignNextTask(worker));
});
}
assignNextTask(worker) {
if (this.taskQueue.length) {
const { task, resolve } = this.taskQueue.shift();
worker.once('message', resolve);
worker.postMessage(task);
}
}
execute(task) {
return new Promise(resolve => {
this.taskQueue.push({ task, resolve });
this.assignNextTask(this.workers.find(w => !w.isBusy));
});
}
}
调试与性能分析
Node.js提供了多种多任务调试工具:
- --inspect-brk参数调试主进程
- worker_threads的调试端口自动递增
- 使用0x生成火焰图分析性能瓶颈
// 获取线程性能数据
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');
// 执行多线程任务
performance.mark('B');
performance.measure('A to B', 'A', 'B');
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn
上一篇:渐进式Web应用(PWA)集成
下一篇:child_process模块