1. 事件驱动机制
- 应用方式:Node.js 本身基于事件驱动架构,在 TCP 服务器中,使用
net
模块创建服务器实例。服务器实例通过 on('connection', callback)
事件监听新的客户端连接,每当有新连接时,执行回调函数处理连接。例如:
const net = require('net');
const server = net.createServer((socket) => {
// 处理新连接
socket.write('Welcome!\n');
socket.on('data', (data) => {
socket.write('You sent: ' + data.toString() + '\n');
});
socket.on('end', () => {
socket.end('Goodbye!\n');
});
});
server.listen(8080, () => {
console.log('Server listening on port 8080');
});
- 优点:
- 高效利用资源,单线程模型避免了多线程上下文切换开销,适合 I/O 密集型任务,如网络通信。
- 简单易用,通过事件回调处理逻辑,代码结构相对清晰。
- 缺点:
- 单线程执行,如果某个回调函数执行时间过长(如复杂计算),会阻塞整个事件循环,影响其他连接的处理。
- 异常处理相对复杂,一个未捕获的异常可能导致整个进程崩溃。
2. 线程池
- 应用方式:Node.js 提供了
worker_threads
模块来实现线程池。对于一些 CPU 密集型任务,可以将任务分配到线程池中执行,避免阻塞事件循环。例如,假设有一个复杂的计算函数 heavyCalculation
:
const { Worker } = require('worker_threads');
function heavyCalculation() {
// 复杂计算逻辑
let result = 0;
for (let i = 0; i < 1000000000; i++) {
result += i;
}
return result;
}
const worker = new Worker(`
const { parentPort } = require('worker_threads');
function heavyCalculation() {
let result = 0;
for (let i = 0; i < 1000000000; i++) {
result += i;
}
return result;
}
parentPort.postMessage(heavyCalculation());
`);
worker.on('message', (result) => {
console.log('计算结果:', result);
});
- 优点:
- 可以将 CPU 密集型任务从事件循环中分离,避免阻塞,提高整体性能。
- 多线程并行处理任务,能充分利用多核 CPU 的优势。
- 缺点:
- 增加了编程复杂度,需要处理线程间通信、同步等问题。
- 线程创建和销毁有一定开销,对于短时间任务,可能得不偿失。
3. 集群模块
- 应用方式:Node.js 的
cluster
模块允许创建多个工作进程,共享服务器端口。主进程负责监听端口并将新连接分配给工作进程。示例如下:
const cluster = require('cluster');
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`主进程 ${process.pid} 正在运行`);
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`工作进程 ${worker.process.pid} 已退出`);
});
} else {
http.createServer((req, res) => {
res.writeHead(200);
res.end('你好,世界!\n');
}).listen(8000, () => {
console.log(`工作进程 ${process.pid} 已启动`);
});
}
- 优点:
- 充分利用多核 CPU 资源,显著提升服务器处理能力。
- 工作进程之间相互隔离,一个工作进程崩溃不会影响其他进程,提高了服务器的稳定性。
- 缺点:
- 编程复杂度增加,需要处理主进程和工作进程间的通信与协调。
- 增加了内存占用,每个工作进程都有自己的内存空间。