Node 进程间怎么通信的

我们都知道 Node 没法操作线程,但可以操作进程,一旦涉及主从模式的进程守护,或者是多机部署的需要,那么都可能碰上需要相互通信的场景,本篇就介绍几种常用方法。

Node 原生 IPC(Inter-Process Communication,进程间通信)支持

最自然的方式,比上一种“正规”一些,具有同样的局限性。其底层是 libuv。

// parent.js
const cp = require('child_process');
const n = cp.fork(`child.js`);

n.on('message', (m) => {
  console.log('父进程收到消息', m);
});

// 使子进程输出: 子进程收到消息 { hello: 'world' }
n.send({ hello: 'world' });

// child.js
process.on('message', (m) => {
  console.log('子进程收到消息', m);
});

// 使父进程输出: 父进程收到消息 { foo: 'bar', baz: null }
process.send({ foo: 'bar', baz: NaN });

运行

> node parent.js
子进程收到消息 { hello: 'world' }
父进程收到消息 { foo: 'bar', baz: null }

libuv 的进程通信能力是怎么来的?

这就要涉及到操作系统的进程间通信方式了,参见深刻理解Linux进程间通信(IPC)。进程间通信一般通过共享内存的方式实现的,使得多个进程可以访问同一块内存空间,是最快的可用 IPC 形式。

通过 sockets

最通用的方式,借助网络完成进程通信,有良好的跨环境能力,但存在网络的性能损耗。

// parent.js
const { spawn } = require('child_process');
const child = spawn('node', ['child'], {
  stdio: [null, null, null, 'pipe'],
});
child.stdio[3].on('data', data => {
  console.log('222', data.toString());
});

// child.js
const net = require('net');
const pipe = net.Socket({ fd: 3 });
pipe.write('killme');

运行

> node parent.js
222 killme

消息队列

最强大的方式,既然要通信,场景还复杂,不妨扩展出一层消息中间件,漂亮地解决各种通信问题.

消息队列可以参见 Rabitmq

或者使用 Redis 的订阅发布,见下例

// parent.js

const cp = require('child_process');
const child = cp.fork(`child.js`);
var Redis = require("ioredis");
var redis = new Redis();
var pub = new Redis();

// 订阅 news 通道,
redis.subscribe("news", function (err, count) {
  // `count` represents the number of channels we are currently subscribed to.

});

// 监听 message 事件。
redis.on("message", function (channel, message) {
  // Receive message Hello world! from channel news
  // Receive message Hello again! from channel music
  console.log("Receive message %s from channel %s", message, channel);
}

// child.js
var Redis = require("ioredis");
var pub = new Redis();

// 发布新消息
pub.publish("news", "Hello world!");
pub.publish("music", "Hello again!");

总结

单机使用则直接 Node 原生 IPC 最为省事,就如 EggJS 中 Master 进程与 Worker 进程的通信。

但你的服务负载需要部署去了多台机器,笔者更建议使用消息队列的方式来相互通信,毕竟追踪多机的 websocket 链路,是挺头疼的一件事。

原文地址:https://www.cnblogs.com/everlose/p/12846737.html