【Node】Node.js 多进程与多线程:Cluster 与 Worker Threads 入门

前言

在 Node.js 开发中,处理 CPU 密集型任务和提升应用性能是常见需求。

今天我们来深入理解 Node.js 提供的两种并发处理方案:Cluster 模块和 Worker Threads 模块。

☺️ 这边要求阅读本文的新手小伙伴要有一个印象:【Cluster】 与【进程】相关,【Worker Threads】 与【线程】相关
小贴士 📚:

✨Cluster 的中文意思是集群 ✨Worker Threads 的中文意思是工作线程

官方定义解析

Node.js 官方文档指出:

"Node.js 进程的集群可用于运行多个 Node.js 实例,这些实例可以在其应用程序线程之间分配工作负载。当不需要进程隔离时,请改用 worker_threads 模块,它允许在单个 Node.js 实例中运行多个应用程序线程。"

核心概念解释

进程(Process)

  • 拥有【独立内存空间】的程序实例
  • 相当于一个独立的应用程序
  • 进程间相互隔离,一个崩溃不会影响其他进程

线程(Thread)

  • 进程内的执行单元
  • 共享进程的内存空间
  • 线程间可以更高效地通信

两种方案的对比

Cluster 模块(多进程)

javascript 复制代码
const cluster = require('cluster')
const os = require('os')

if (cluster.isPrimary) {
    // 主进程:创建工作进程
    for (let i = 0; i < os.cpus().length; i++) {
        cluster.fork()
    }
} else {
    // 工作进程:启动服务器
    require('./server.js')
}

适用场景

  • HTTP 服务器负载均衡
  • 需要高隔离性的任务
  • 利用多核 CPU 处理并发请求

特点

  • ✅ 进程隔离,稳定性高
  • ✅ 充分利用多核 CPU
  • ❌ 内存开销较大
  • ❌ 进程间通信成本较高

Worker Threads 模块(多线程)

javascript 复制代码
const {Worker} = require('worker_threads')

function runWorker(data) {
    return new Promise((resolve, reject) => {
        const worker = new Worker(
            `
      const { parentPort } = require('worker_threads');
      parentPort.on('message', (data) => {
        // 执行计算密集型任务
        const result = heavyCalculation(data);
        parentPort.postMessage(result);
      });
    `,
            {eval: true}
        )

        worker.on('message', resolve)
        worker.on('error', reject)
        worker.postMessage(data)
    })
}

适用场景

  • CPU 密集型计算任务
  • 图像/视频处理
  • 大数据分析
  • 加密解密操作

特点

  • ✅ 内存共享,开销较小
  • ✅ 线程间通信高效
  • ❌ 隔离性较差,一个线程崩溃可能影响整个进程
  • ❌ 需要处理线程同步问题

选择指南

什么时候用 Cluster?

  • 构建 Web 服务器,需要处理大量并发连接。其实可以联想到 pm2 的多进程模式 ------ 经过了解,得知 PM2 的集群模式(pm2 start app.js -i 4)在底层正是使用了 Node.js 的 Cluster 模块 来实现的。
  • 任务需要高度的稳定性和隔离性
  • 希望充分利用多核 CPU 性能

什么时候用 Worker Threads?

  • 需要执行复杂的数学计算或数据处理
  • 任务需要共享大量数据
  • 希望减少内存开销
  • 在单个进程中需要并行处理多个任务

实际应用示例

场景:图像处理服务

javascript 复制代码
// 使用 Worker Threads 处理图像
const {Worker} = require('worker_threads')

class ImageProcessor {
    async processImages(images) {
        const workers = images.map(image => this.createWorker('./image-worker.js', image))

        const results = await Promise.all(workers)
        return results
    }

    createWorker(workerPath, data) {
        return new Promise((resolve, reject) => {
            const worker = new Worker(workerPath, {workerData: data})
            worker.on('message', resolve)
            worker.on('error', reject)
        })
    }
}

场景:高并发 Web 服务

javascript 复制代码
// 使用 Cluster 创建 Web 服务器集群
const cluster = require('cluster')
const http = require('http')
const numCPUs = require('os').cpus().length

if (cluster.isPrimary) {
    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} 已启动`)
}

性能考量

  1. 内存使用:Worker Threads 通常比 Cluster 更节省内存
  2. 启动速度:线程启动比进程启动更快
  3. 通信成本:线程间通信比进程间通信更高效
  4. 稳定性:Cluster 提供更好的故障隔离

总结

这边简单做个总结 🍃

  • Cluster 适合需要高隔离性和稳定性的 I/O 密集型任务
  • Worker Threads 适合需要高效内存使用的 CPU 密集型任务
相关推荐
牛奔10 小时前
Go 如何避免频繁抢占?
开发语言·后端·golang
想用offer打牌15 小时前
MCP (Model Context Protocol) 技术理解 - 第二篇
后端·aigc·mcp
崔庆才丨静觅16 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby606117 小时前
完成前端时间处理的另一块版图
前端·github·web components
KYGALYX17 小时前
服务异步通信
开发语言·后端·微服务·ruby
掘了17 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅17 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅17 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
爬山算法17 小时前
Hibernate(90)如何在故障注入测试中使用Hibernate?
java·后端·hibernate
崔庆才丨静觅18 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端