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 鏈路,是挺頭疼的一件事。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM