【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 密集型任务
相关推荐
AAA大运重卡何师傅(专跑国道)21 分钟前
力扣hot100
服务器·前端·数据库
GISer_Jing36 分钟前
前端沙箱开源项目推荐(React/Next/Vue优先)
前端·react.js·开源
暗冰ཏོ36 分钟前
Go 语言从入门到后端项目实战完整指南
开发语言·后端·golang·go·go语言
云水一下39 分钟前
CSS3从零基础到精通(三):动感地带——过渡、动画、变形与响应式
前端·css3
霸道流氓气质1 小时前
Windows批处理脚本完整指南:可移植的交互式SpringBoot项目管理
windows·spring boot·后端
小杍随笔1 小时前
【Rust 工具链管理完全指南:rustup toolchain 命令实战详解】
开发语言·后端·rust
五月君_1 小时前
放弃 Python,Kimi 用 TS + Node.js 重写了一个 Kimi Code
开发语言·python·node.js
还是鼠鼠1 小时前
AI掘金头条新闻系统 (Toutiao News)-获取用户信息
后端·python·mysql·fastapi·web
BingoGo1 小时前
免费可商用 PHP 管理后台 CatchAdmin V5.3.1 发布 后台打包直降 5s 内
后端·php
JaguarJack1 小时前
免费可商用 PHP 管理后台 CatchAdmin V5.3.1 发布 后台打包直降 5s 内
后端·php·laravel