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

hiz5n14c  于 2022-12-17  发布在  Redis
关注(0)|答案(6)|浏览(137)

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

**EDIT:**进程可能在不同的计算机上运行

mdfafbf1

mdfafbf11#

如果你想把消息从一台机器发送到另一台机器,并且不关心回调,那么Redis发布/订阅是最好的解决方案,它非常容易实现,而且Redis速度非常快。
首先你必须在你的机器上安装Redis。
连接到Redis非常简单:

var client = require('redis').createClient(redis_port, redis_host);

但是不要忘记在防火墙中打开Redis端口!
然后,您必须为每台计算机订阅某个频道:

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

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

您可以跳过your_namespace而使用全局名称空间,但您迟早会后悔的。
发送消息也非常简单:

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

如果您想发送不同类型的信息,您可以使用pmessages代替messages:

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));
};

最佳做法是按功能命名进程(或计算机)(例如'send_email')。在这种情况下,如果进程(或计算机)实现多个功能,则可以订阅多个通道。
实际上,使用redis建立双向通信是可能的,但这更棘手,因为它需要为每条消息添加唯一的回调通道名称,以便在不丢失上下文的情况下接收回调。
所以,我的结论是:如果您需要“发送后忘记”的沟通,请使用Redis;如果您需要全面的双向沟通,请研究其他解决方案

fnvucqvd

fnvucqvd2#

为什么不使用ZeroMQ/0mq来进行IPC呢?Redis(一个数据库)对于像IPC这样简单的事情来说太过了。
引用指南:
大MQ(ZeroMQ,0 MQ,zmq)看起来像一个可嵌入的网络库,但实际上却像一个并发框架。它提供的套接字可以跨进程内、进程间、TCP和多播等各种传输方式承载原子消息。您可以使用fanout、pub-sub、任务分发、它的速度足以成为集群产品的结构。它的异步I/O模型为您提供了可伸缩的多核应用程序,构建为异步消息处理任务。
使用0 MQ的优点(甚至是通过Node核心中的网络库提供的vanilla套接字,减去0 MQ套接字提供的所有特性)是没有主进程。它的无代理设置最适合您描述的场景。如果您只是将消息从一个中央进程推送到各个节点,则可以使用0 mq中的PUB/SUB套接字(也支持通过PGM/EPGM的IP多播)。除此之外,0 mq还提供了各种不同的套接字类型(PUSH/PULL/XREP/XREQ/ROUTER/DEALER),您可以使用这些套接字创建自定义设备。
从这个优秀的指南开始:http://zguide.zeromq.org/page:all
对于0 MQ 2.x:
http://github.com/JustinTulloss/zeromq.node
对于0 MQ 3.x(上述模块的分支,支持PUBSUB的PUBLISHER端过滤):
http://github.com/shripadk/zeromq.node

lndjwyie

lndjwyie3#

在这个问题被提出4年多之后,出现了一个进程间通信模块node-ipc,它支持unix/windows socket在同一台机器上通信,支持TCP、TLS和UDP,声称至少socket、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();

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);
            }
        );
    }
);

我目前正在评估这个模块是否可以替代本地ipc(但将来可能是远程ipc),作为旧的stdin/stdout解决方案的替代品,也许我会在完成后扩展我的答案,给予更多关于这个模块如何工作以及工作得有多好的信息。

pkln4tw6

pkln4tw64#

我将从节点提供的内置功能开始。
您可以使用进程信令,例如:

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

该信令
当进程接收到信号时发出。参见sigaction(2)获得标准POSIX信号名的列表,如SIGINT、SIGUSR 1等。
一旦你知道了进程,你可以spwn一个child-process,并将它连接到message事件来检索和发送消息。当使用child_process.fork()时,你可以使用child.send(message, [sendHandle])写入子进程,消息由子进程上的“message”事件接收。
另外-你可以使用集群。集群模块允许你轻松地创建一个进程网络,所有进程都共享服务器端口。

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);
}

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

k4aesqcs

k4aesqcs5#

了解节点信使
https://github.com/weixiyen/messenger.js
通过自动维护的连接池,轻松满足大多数需求(发布/订阅...即发即忘...发送/请求)

wn9m85ua

wn9m85ua6#

我们正在开发多进程节点app,需要处理大量的实时跨进程消息。
我们先试了一下redis-pub-sub,没有达到要求。
然后尝试tcp套接字,这是更好的,但仍然不是最好的。
所以我们切换到UDP数据报,这是快得多。
下面是代码库,只有几行代码。https://github.com/SGF-Games/node-udpcomm

相关问题