c语言编程笔录

首页 >   > 笔记大全

笔记大全

详解node中进程通信的几种实现方式

更新时间:2023-12-04

Node.js中进程通信的基本原理

Node.js是基于V8引擎的,因此Node应用程序本质上是单线程运行的。然而,Node为了提高处理能力,提供了child_process模块,可以将多个进程运行在同一个应用程序当中。

进程间通信(IPC)是必不可少的,Node为此提供了多种IPC机制,包括:process.send()child_process.spawn()child_process.fork()cluster.fork()等等。下面我们将逐个介绍这些IPC机制。

使用process.send()进行进程通信

process.send()方法是一个进程中用于发送消息的方法,当Node.js应用程序运行在可以创建子进程的环境中时,这个方法可以用来将消息发送到一个子进程或者父进程。

以下是一个简单的例子:

    // 父进程代码
    const child_process=require('child_process');
    const child=child_process.fork('child.js');
    
    child.on('message', (msg)=> {
      console.log('父进程收到了消息:', msg);
    });
    
    child.send('Hello, child process!');
    // 子进程代码(child.js文件)
    process.on('message', (msg)=> {
      console.log('子进程收到了消息:', msg);
    });

    process.send('Hello, parent process!');

上面的代码中,父进程创建了一个子进程,并使用child.send()方法向子进程发送了一条消息。子进程使用process.on('message')方法监听消息事件,并使用process.send()方法向父进程发送了一条消息。父进程也使用child.on('message')方法监听消息事件,进而得到了子进程发送的消息。

使用child_process.spawn()创建进程

child_process.spawn()方法是一种创建新进程的方式,它返回一个ChildProcess对象,这个对象有stdinstdoutstderr等流对象,可以通过这些流对象进行输入输出操作。

以下是一个简单的例子:

    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(`子进程退出码:${code}`);
    });

上面的代码中,使用spawn()方法创建了一个新进程,并向ls命令传递了两个参数。ls.stdout.on()事件监听了子进程向标准输出流中写入数据的事件,并将其输出到控制台上。

使用child_process.fork()创建进程

child_process.fork()方法是一种创建新进程的方式,与spawn()方法类似,它也返回一个ChildProcess对象。不同之处在于,fork()方法创建的新进程可以与父进程之间建立一个IPC通道。

以下是一个简单的例子:

    // 父进程代码
    const child_process=require('child_process');
    const child=child_process.fork('child.js');

    child.on('message', (msg)=> {
      console.log('父进程收到了消息:', msg);
    });

    child.send({ hello: 'world' });
    // 子进程代码(child.js文件)
    process.on('message', (msg)=> {
      console.log('子进程收到了消息:', msg);
    });

    process.send({ foo: 'bar' });

在上面的代码中,父进程使用fork()方法创建了一个子进程,并向子进程发送了一条消息。子进程使用process.on('message')方法监听消息事件,并使用process.send()方法向父进程发送了一条消息。

使用cluster.fork()创建进程

cluster.fork()方法是一种创建子进程的方式,与child_process.fork()类似。当调用cluster.fork()方法时,Node会创建一个子进程并将其管理起来,这个子进程和其他进程(可能是其他子进程)共享同一个端口和地址。

以下是一个简单的例子:

    // 主进程代码
    const cluster=require('cluster');
    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 {
      console.log(`工作进程 ${process.pid} 已启动`);
    }

在上面的代码中,主进程使用cluster.isMaster属性判断当前进程是否为主进程,当当前进程是主进程时,它会调用cluster.fork()方法创建多个工作进程。当有任一个工作进程退出时,主进程会通过cluster.on('exit')事件监听到,然后再创建一个新的工作进程。

总结

Node.js中提供了多种IPC机制,包括process.send()child_process.spawn()child_process.fork()cluster.fork()等,用于不同场景下的进程间通信。开发者可以根据自己的需求和性能要求选择合适的机制。