什么是最有效的node.js进程间通信库/方法?

Dud*_*lul 57 javascript interprocess redis node.js

我们有几个node.js进程应该能够传递消息,这样做最有效的方法是什么?如何使用node_redis pub/sub

编辑:进程可能在不同的机器上运行

Leo*_*tny 42

如果您想将消息从一台机器发送到另一台机器并且不关心回调,那么Redis pub/sub是最佳解决方案.它实现起来非常简单,Redis非常快.

首先,您必须在其中一台机器上安装Redis.

它很容易连接到Redis:

var client = require('redis').createClient(redis_port, redis_host);
Run Code Online (Sandbox Code Playgroud)

但是不要忘记在防火墙中打开Redis端口!

然后你必须将每台机器订阅到某个频道:

client.on('ready', function() {
  return client.subscribe('your_namespace:machine_name');
});

client.on('message', function(channel, json_message) {
  var message;
  message = JSON.parse(message);
  // do whatever you vant with the message
});
Run Code Online (Sandbox Code Playgroud)

您可以跳过your_namespace并使用全局命名空间,但迟早会后悔的.

发送消息也很容易:

var send_message = function(machine_name, message) {
  return client.publish("your_namespace:" + machine_name, JSON.stringify(message));
};
Run Code Online (Sandbox Code Playgroud)

如果要发送不同类型的消息,可以使用pmessages而不是消息:

client.on('ready', function() {
  return client.psubscribe('your_namespace:machine_name:*');
});

client.on('pmessage', function(pattern, channel, json_message) {
  // pattern === 'your_namespace:machine_name:*'
  // channel === 'your_namespace:machine_name:'+message_type
  var message = JSON.parse(message);
  var message_type = channel.split(':')[2];
  // do whatever you want with the message and message_type
});

send_message = function(machine_name, message_type, message) {
  return client.publish([
    'your_namespace',
    machine_name,
    message_type
  ].join(':'), JSON.stringify(message));
};
Run Code Online (Sandbox Code Playgroud)

最佳实践是根据其功能(例如'send_email')命名您的流程(或机器).在这种情况下,如果进程(或机器)实现多个功能,则它可以订阅多个通道.

实际上,可以使用redis构建双向通信.但它更棘手,因为它需要为每条消息添加唯一的回调通道名称,以便在不丢失上下文的情况下接收回调.

因此,我的结论是:如果您需要"发送并忘记"通信,请使用Redis,如果您需要完全成熟的双向通信,请研究其他解决方案.


Shr*_*hna 34

为什么不将ZeroMQ/0mq用于IPC?Redis(一个数据库)因为做一些像IPC那样简单的事情而被过度杀戮.

引用指南:

ØMQ(ZeroMQ,0MQ,zmq)看起来像一个可嵌入的网络库,但就像一个并发框架.它为您提供了在各种传输中传输原子消息的套接字,如进程内,进程间,TCP和多播.您可以使用扇出,发布 - 订阅,任务分发和请求 - 回复等模式连接N到N的套接字.它足够快,可以成为集群产品的结构.其异步I/O模型为您提供可扩展的多核应用程序,构建为异步消息处理任务.

使用0MQ(甚至通过Node核心中的网络库的vanilla套接字,减去0MQ套接字提供的所有功能)的优点是没有主进程.其无代理设置最适合您描述的场景.如果您只是从一个中央进程向各个节点推送消息,则可以在0mq中使用PUB/SUB套接字(也支持通过PGM/EPGM进行IP多播).除此之外,0mq还提供各种不同的套接字类型(PUSH/PULL/XREP/XREQ/ROUTER/DEALER),您可以使用它们创建自定义设备.

从这本优秀的指南开始:http://zguide.zeromq.org/page: all

对于0MQ 2.x:

http://github.com/JustinTulloss/zeromq.node

对于0MQ 3.x(上述模块的一个分支.这支持PUBSUB的PUBLISHER侧过滤):

http://github.com/shripadk/zeromq.node

  • 设置需要数年时间.而且难以维持.除了node.js之外,它只有一个节点包装器,这使得修复问题变得更加困难 (4认同)

mor*_*n.c 31

在询问问题超过4年后,有一个名为node-ipc的进程间通信模块.它支持unix/windows套接字,用于在同一台机器上进行通信,以及TCP,TLS和UDP,声称至少套接字,TCP和UDP是稳定的.

以下是从github存储库的文档中获取的一个小示例:

适用于Unix套接字,Windows套接字和TCP套接字的服务器

var ipc=require('node-ipc');

ipc.config.id   = 'world';
ipc.config.retry= 1500;

ipc.serve(
    function(){
        ipc.server.on(
            'message',
            function(data,socket){
                ipc.log('got a message : '.debug, data);
                ipc.server.emit(
                    socket,
                    'message',
                    data+' world!'
                );
            }
        );
    }
);

ipc.server.start();
Run Code Online (Sandbox Code Playgroud)

Unix套接字和TCP套接字的客户端

var ipc=require('node-ipc');

ipc.config.id   = 'hello';
ipc.config.retry= 1500;

ipc.connectTo(
    'world',
    function(){
        ipc.of.world.on(
            'connect',
            function(){
                ipc.log('## connected to world ##'.rainbow, ipc.config.delay);
                ipc.of.world.emit(
                    'message',
                    'hello'
                )
            }
        );
        ipc.of.world.on(
            'disconnect',
            function(){
                ipc.log('disconnected from world'.notice);
            }
        );
        ipc.of.world.on(
            'message',
            function(data){
                ipc.log('got a message from world : '.debug, data);
            }
        );
    }
);
Run Code Online (Sandbox Code Playgroud)

我目前正在评估这个模块的替换本地ipc(但将来可能是远程ipc)作为stdin/stdout的旧解决方案的替代品.当我完成这个模块的工作原理时,我可以扩展我的答案.

  • 2022 年通知:node-ipc 中插入了恶意软件。不良版本已从主 npm 存储库中删除。我看到很多人都在使用v9.2.1(npm download stats),这似乎是事件发生之前的版本。最新版本(v11)包含“peacenotwar”依赖项。 (5认同)
  • node-ipc与ZeroMQ相比如何?哪一个会更快? (4认同)
  • 老实说,我不喜欢它。node-ipc 与 String 原型混淆(如您在上面的示例中看到的“## 连接到世界 ##'.rainbow”),并且其界面对于 2019 年标准来说有点过时。 (2认同)

Sag*_*fek 8

我将从节点提供的内置功能开始.
您可以使用以下流程信令:

process.on('SIGINT', function () {
  console.log('Got SIGINT.  Press Control-D to exit.');
});
Run Code Online (Sandbox Code Playgroud)

这个信号

当进程收到信号时发出.有关标准POSIX信号名称列表,请参阅sigaction(2),例如SIGINT,SIGUSR1等.

一旦了解了进程,就可以创建一个子进程并将其连接到message事件以进行反向并发送消息.使用时,child_process.fork()您可以使用儿童写信给儿童,child.send(message, [sendHandle])并通过儿童的"消息"事件接收消息.

此外 - 您可以使用群集.群集模块允许您轻松创建所有共享服务器端口的进程网络.

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', function(worker, code, signal) {
    console.log('worker ' + worker.process.pid + ' died');
  });
} else {
  // Workers can share any TCP connection
  // In this case its a HTTP server
  http.createServer(function(req, res) {
    res.writeHead(200);
    res.end("hello world\n");
  }).listen(8000);
}
Run Code Online (Sandbox Code Playgroud)

对于第三方服务,您可以检查: hook.io,signalsbean.

  • -1:“进程可能在不同的机器上运行”。节点在进程与其子进程(同一台机器)之间有一个内置通道。OP 需要与来自不同机器的 2 个不同进程进行通信。 (2认同)