Node.js Cluster 模块
Node.js 的 cluster
模块允许你轻松创建共享同一服务器端口的子进程(worker processes)。由于 Node.js 是单线程的,cluster
模块可以帮助我们充分利用多核 CPU 系统的性能。
简单来说,cluster
模块就像是一家餐厅的经理,它创建多个服务员(worker)来处理顾客(请求),而不是让一个服务员处理所有顾客。
为什么需要 Cluster 模块?
提高性能:现代 CPU 通常有多个核心,但 Node.js 默认只使用一个核心。
cluster
模块可以让你利用所有可用的 CPU 核心。提高可靠性:如果一个 worker 崩溃了,其他 worker 可以继续处理请求,主进程可以重新启动崩溃的 worker。
零停机时间:可以逐个重启 worker 来实现代码更新,而不会中断服务。
Cluster 模块基础用法
实例
const http = require('http');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
console.log(`主进程 ${process.pid} 正在运行`);
// 衍生 worker 进程
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`worker ${worker.process.pid} 已退出`);
});
} else {
// Worker 可以共享同一个 TCP 连接
// 这里是一个 HTTP 服务器
http.createServer((req, res) => {
res.writeHead(200);
res.end('你好世界\n');
}).listen(8000);
console.log(`Worker ${process.pid} 已启动`);
}
核心概念解析
主进程(Master Process)
- 负责管理所有 worker 进程
- 通常不处理实际请求
- 可以监听 worker 的各种事件
Worker 进程
- 实际处理请求的子进程
- 每个 worker 都是独立的 Node.js 进程
- 共享同一个服务器端口
Cluster 模块常用 API
cluster.fork()
创建一个新的 worker 进程。调用这个方法会返回一个 worker 对象。
cluster.isMaster
如果是主进程,则为 true
。
cluster.isWorker
如果是 worker 进程,则为 true
。
cluster.workers
包含所有活跃 worker 对象的哈希表,以 worker.id
作为键名。
实际应用场景
1. 负载均衡
实例
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;
if (cluster.isMaster) {
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
} else {
require('./app'); // 你的应用入口文件
}
2. 优雅重启
实例
console.log(`Worker ${worker.process.pid} 退出`);
// 可以在这里重新 fork 一个新的 worker
cluster.fork();
});
3. 进程间通信
实例
worker.send('Hello worker!');
// Worker 接收消息
process.on('message', (msg) => {
console.log(`Worker ${process.pid} 收到消息: ${msg}`);
});
性能优化技巧
根据 CPU 核心数创建 worker:通常建议 worker 数量等于 CPU 核心数。
共享端口:所有 worker 共享同一个端口,操作系统会自动分配请求到不同的 worker。
共享连接:对于长连接(如 WebSocket),需要考虑连接如何分配到不同的 worker。
共享状态:worker 之间不共享内存,需要使用 Redis 等外部存储来共享状态。
常见问题与解决方案
1. 内存泄漏
每个 worker 是独立进程,一个 worker 的内存泄漏不会影响其他 worker,但需要监控并重启异常的 worker。
2. 会话保持
如果需要会话保持,可以使用粘性会话(sticky session)或将会话数据存储在外部(如 Redis)。
3. 文件描述符限制
大量 worker 可能导致文件描述符耗尽,需要调整系统限制:
实例
Cluster 模块的替代方案
虽然 cluster
模块很强大,但也有其他选择:
- PM2:进程管理器,内置负载均衡和监控功能
- Nginx:反向代理,可以在多个 Node.js 实例间负载均衡
- Kubernete:容器编排系统,可以自动扩展 Node.js 服务
总结
Node.js 的 cluster
模块是构建高性能、高可用性网络服务的重要工具。通过创建多个 worker 进程,我们可以:
- 充分利用多核 CPU 的性能
- 提高应用的可靠性
- 实现零停机部署
虽然设置和管理多进程应用比单进程复杂,但对于生产环境中的 Node.js 应用来说,使用 cluster
模块或类似的解决方案几乎是必须的。
希望这篇指南能帮助你理解和使用 Node.js 的 cluster
模块!
点我分享笔记