Nodejs多进程

栏目: NodeJs 发布时间:2024-12-05

Node.js 多进程教程

node.js 是一个单线程的运行时环境,基于事件驱动和非阻塞 I/O 模型。虽然这种设计使得 Node.js 在处理 I/O 密集型任务时非常高效,但在处理 CPU 密集型任务时可能会遇到性能瓶颈。为了充分利用多核 CPU 的计算能力,Node.js 提供了多进程的能力,允许开发者创建多个独立的进程来并行处理任务。

在这个教程中,我们将学习如何使用 Node.js 的 child_process 模块来创建和管理多进程。此外,我们还将讨论如何使用 cluster 模块来自动地在多个核心上分发请求。

第一部分:使用 child_process 模块

child_process 模块允许 Node.js 代码创建子进程,并与它们进行通信。这个模块提供了几种方法来创建子进程,包括 spawn()exec()execFile()fork()

  1. spawn() 方法spawn() 方法用于创建一个新的进程来执行指定的命令或脚本。

    const { spawn } = require('child_process');
    
    const ls = spawn('ls', ['-lh', '/usr']);
    
    ls.stdout.on('data', (data) => {
      console.log(`stdout: ${data}`);
    });
    
    ls.stderr.on('data', (data) => {
      console.error(`stderr: ${data}`);
    });
    
    ls.on('close', (code) => {
      console.log(`child process exited with code ${code}`);
    });
    
  2. exec() 方法exec() 方法用于执行一个命令,并将缓冲区中的数据作为回调函数的参数返回。

    const { exec } = require('child_process');
    
    exec('node -v', (error, stdout, stderr) => {
      if (error) {
        console.error(`exec error: ${error}`);
        return;
      }
      console.log(`stdout: ${stdout}`);
      console.error(`stderr: ${stderr}`);
    });
    
  3. fork() 方法fork() 方法是 spawn() 方法的一个特殊形式,它专门用于创建 Node.js 子进程。与 spawn() 不同,fork() 允许父进程和子进程之间通过发送消息来进行通信。

    // parent.js
    const { fork } = require('child_process');
    const child = fork('child.js');
    
    child.on('message', (msg) => {
      console.log('Message from child', msg);
    });
    
    child.send({ hello: 'world' });
    
    // child.js
    process.on('message', (msg) => {
      console.log('Message from parent:', msg);
      process.send({ reply: 'Hello from child' });
    });
    

第二部分:使用 cluster 模块

cluster 模块允许你轻松地创建共享服务器端口的子进程。这对于充分利用多核系统特别有用,因为它允许 Node.js 应用程序并行处理多个请求。

  1. 基本用法

    const cluster = require('cluster');
    const http = require('http');
    const numCPUs = require('os').cpus().length;
    
    if (cluster.isMaster) {
      console.log(`Master ${process.pid} is running`);
    
      // Fork workers.
      for (let i = 0; i < numCPUs; i++) {
        cluster.fork();
      }
    
      cluster.on('exit', (worker, code, signal) => {
        console.log(`worker ${worker.process.pid} died`);
      });
    
    } else {
      // Workers can share any TCP connection
      // In this case it is an HTTP server
      http.createServer((req, res) => {
        res.writeHead(200);
        res.end('hello world\n');
      }).listen(8000);
    
      console.log(`Worker ${process.pid} started`);
    }
    

    在这个例子中,主进程(Master)创建了与 CPU 核心数量相等的子进程(Workers)。每个子进程都监听相同的端口(8000),并且由于 cluster 模块的工作方式,这些请求会被自动分发到不同的子进程中。

  2. 与子进程通信

    虽然 cluster 模块主要用于负载均衡,但你也可以通过主进程和子进程之间的消息传递来进行更复杂的通信。

    // 在主进程中
    cluster.on('online', (worker) => {
      worker.send({ cmd: 'notifyOnline' });
    });
    
    // 在子进程中
    process.on('message', (message) => {
      if (message.cmd === 'notifyOnline') {
        console.log('Worker received online message');
      }
    });
    

结论

通过这篇教程,你已经学习了如何使用 Node.js 的 child_processcluster 模块来创建和管理多进程。child_process 模块提供了灵活的方式来执行外部命令和脚本,并与它们进行通信,而 cluster 模块则专门用于在多个核心上分发 Node.js 应用程序的请求。这些工具可以帮助你充分利用多核 CPU 的计算能力,提高 Node.js 应用程序的性能和可扩展性。

本文地址:https://www.tides.cn/p_node-process