Node.js cluster模块详解

Node.js cluster 模块详解

cluster 模块允许你轻松创建共享同一服务器端口的子进程(worker),充分利用多核 CPU 的性能。它是 Node.js 实现高并发的重要工具。

核心概念

  1. 主进程(Master):负责管理工作进程,通常不处理实际请求
  2. 工作进程(Worker):实际处理请求的子进程
  3. IPC 通信:主进程和工作进程之间通过进程间通信(IPC)交换消息

基本使用

javascript 复制代码
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 {
  // 工作进程可以共享任何 TCP 连接
  // 在本例子中,它是一个 HTTP 服务器
  http.createServer((req, res) => {
    res.writeHead(200);
    res.end('你好世界\n');
  }).listen(8000);

  console.log(`工作进程 ${process.pid} 已启动`);
}

主要 API

cluster.isMaster / cluster.isWorker

  • cluster.isMaster: 如果是主进程则为 true
  • cluster.isWorker: 如果是工作进程则为 true

cluster.fork([env])

  • 衍生一个新的工作进程
  • 可以传入环境变量对象 env
  • 返回 Worker 对象

cluster.setupMaster([settings])

  • 修改默认的 fork 行为
  • settings 可选参数:
    • exec: 工作进程文件路径
    • args: 传递给工作进程的参数
    • silent: 是否将输出发送到父进程的 stdio

cluster.worker

  • 当前工作进程对象的引用(仅在子进程中可用)

cluster.workers

  • 存储所有活跃工作进程的哈希表
  • 键是工作进程 ID,值是 Worker 对象

Worker 类

worker.id

  • 每个新创建的工作进程都有唯一的 ID

worker.process

  • 工作进程的 ChildProcess 对象

worker.send(message[, sendHandle][, callback])

  • 向工作进程发送消息
  • 可以通过 sendHandle 发送句柄

worker.kill([signal='SIGTERM'])

  • 杀死工作进程

worker.disconnect()

  • 断开工作进程与主进程的连接

事件

cluster.on('fork', worker)

  • 当新的工作进程被 fork 时触发

cluster.on('online', worker)

  • 当工作进程开始运行后触发

cluster.on('listening', worker, address)

  • 当工作进程调用 listen() 后触发

cluster.on('disconnect', worker)

  • 当工作进程的 IPC 通道断开时触发

cluster.on('exit', worker, code, signal)

  • 当工作进程退出时触发

cluster.on('message', worker, message, handle)

  • 当工作进程发送消息时触发

高级特性

1. 进程间通信

javascript 复制代码
if (cluster.isMaster) {
  const worker = cluster.fork();
  worker.send('主进程发送的消息');
  worker.on('message', (msg) => {
    console.log('收到工作进程消息:', msg);
  });
} else {
  process.on('message', (msg) => {
    console.log('收到主进程消息:', msg);
    process.send('工作进程回复');
  });
}

2. 优雅重启

javascript 复制代码
if (cluster.isMaster) {
  // 启动工作进程
  const worker = cluster.fork();

  // 收到重启信号
  process.on('SIGUSR2', () => {
    const newWorker = cluster.fork();
    newWorker.on('listening', () => {
      worker.kill('SIGTERM');
    });
  });
} else {
  require('./server'); // 你的应用代码
}

3. 共享服务器端口

多个工作进程可以共享同一个端口:

javascript 复制代码
if (cluster.isMaster) {
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  const net = require('net');
  net.createServer((socket) => {
    socket.end('由工作进程 ' + process.pid + ' 处理');
  }).listen(8000);
}

性能注意事项

  1. 负载均衡:Node.js 的 cluster 模块默认使用轮询调度(除了 Windows)
  2. 状态共享:工作进程之间不共享内存,需要通过 IPC 或外部存储(如 Redis)共享状态
  3. 长连接:对于 WebSocket 等长连接应用,需要确保同一客户端始终连接到同一工作进程

实际应用示例

Express 应用集群化

javascript 复制代码
const cluster = require('cluster');
const express = require('express');
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} 已退出`);
    // 自动重启
    cluster.fork();
  });
} else {
  const app = express();
  
  app.get('/', (req, res) => {
    res.send(`由工作进程 ${process.pid} 处理`);
  });

  app.listen(3000, () => {
    console.log(`工作进程 ${process.pid} 已启动`);
  });
}

常见问题解决方案

  1. 工作进程崩溃 :监听 exit 事件并自动重启
  2. 零停机部署 :使用 SIGUSR2 信号实现优雅重启
  3. 会话保持:使用粘性会话(sticky session)或外部会话存储

总结

cluster 模块是 Node.js 实现多进程的核心模块,能够显著提升应用的并发处理能力。通过合理配置和管理工作进程,可以构建高可用、高性能的 Node.js 应用。

相关推荐
魔云连洲3 小时前
用Webpack 基础配置快速搭建项目开发环境
前端·webpack·node.js
石页玩逆向3 小时前
某企查-某度旋转验证码V2算法分析
node.js
·薯条大王4 小时前
Node.js 模块包的管理和使用是
node.js
熊猫片沃子6 小时前
使用nvm解决nodejs多版本问题,难道不香吗?
前端·npm·node.js
Mintopia6 小时前
Node.js 与前端现代工具链进阶指南
前端·javascript·node.js
孟陬8 小时前
Node.js 如何检测 script 脚本是在项目本身运行
node.js·bun
玲小珑10 小时前
5分钟学会LLM开发系列教程(五)Agent的最终形态LangGraph
langchain·node.js·ai编程
林太白11 小时前
Nest如何连接数据库
前端·后端·node.js
A-Kamen19 小时前
Webpack vs Vite:深度对比与实战示例,如何选择最佳构建工具?
前端·webpack·node.js
OpenTiny社区1 天前
Node.js技术原理分析系列7——Node.js模块加载方式分析
前端·node.js