什么是最有效的node.js进程间通信库/方法?
我们有几个node.js进程应该能够传递消息,那么最有效的方法是什么? 如何使用node_redis pub / sub
编辑:进程可能运行在不同的机器上
如果您想将消息从一台机器发送到另一台机器,而不关心callback,那么Redis pub / sub是最好的解决scheme。 这很容易实现,而且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(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)); };
如果你想发送不同types的消息,你可以使用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)); };
最好的做法是通过它们的function来命名你的进程(或机器)(例如'send_email'
)。 在这种情况下,如果进程(或机器)实现了多个function,则可以订阅多个通道。
实际上,使用redisbuild立双向通信是可能的。 但它更棘手,因为它需要添加唯一的callback通道名称到每个消息,以接收callback而不丢失上下文。
所以,我的结论是: 如果您需要“发送和忘记”通信,请使用Redis,如果您需要全面的双向通信,请调查另一种解决scheme 。
为什么不把ZeroMQ / 0mq用于IPC? Redis(一个数据库)因为像IPC这样简单的事情而被过度杀死。
引用指南:
ØMQ(ZeroMQ,0MQ,zmq)看起来像一个可embedded的networking库,但是像一个并发框架。 它给你提供了跨越各种传输(如进程内,进程间,TCP和多播)的primefaces消息的套接字。 您可以将套接字N对N连接到fanout,pub-sub,任务分配和请求回复等模式。 成为集群产品的结构已经足够快了。 其asynchronousI / O模型为您提供可扩展的多核应用程序,构build为asynchronous消息处理任务。
使用0MQ(甚至是通过Node核心网库的vanilla套接字,减去0MQ套接字提供的所有function)的优点是没有主进程。 它的经纪人设置最适合你描述的场景。 如果您只是从一个中央处理器向各个节点推送消息,则可以使用0mq中的PUB / SUB套接字(也支持通过PGM / EPGM的IP多播)。 除此之外,0mq还提供了各种不同的套接字types(PUSH / PULL / XREP / XREQ / ROUTER / DEALER),您可以使用它们创build自定义设备。
从这个优秀的指南开始:http: //zguide.zeromq.org/page : all
对于0MQ 2.x:
http://github.com/JustinTulloss/zeromq.node
对于0MQ 3.x(上述模块的一个分支,这支持PUBSUB的PUBLISHER侧过滤):
问题提出四年多以后,有一个名为node-ipc的进程间通信模块。 它支持在同一台机器上进行通信的unix / windows套接字以及TCP,TLS和UDP,声称至lesssocket,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在未来)作为替代旧的解决scheme通过stdin /标准输出。 也许我会扩大我的答案,当我完成了一些更多的信息,这个模块的工作原理。
我将从节点提供的内置function开始。
你可以使用过程信号如:
process.on('SIGINT', function () { console.log('Got SIGINT. Press Control-D to exit.'); });
这个信号
当进程收到信号时发出。 有关标准POSIX信号名称(如SIGINT,SIGUSR1等)的列表,请参阅sigaction(2)。
一旦你了解了进程,你就可以调用一个subprocess,并将其挂接到message
事件中来回顾并发送消息。 当使用child_process.fork()
你可以使用child.send(message, [sendHandle])
写给孩子child.send(message, [sendHandle])
并通过孩子上的'message'事件接收消息。
另外 – 你可以使用群集 。 群集模块允许您轻松创build全部共享服务器端口的进程networking。
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.io , 信号和bean 。
我们正在开发多进程节点应用程序,这是处理大量实时跨进程消息所必需的。
我们首先尝试了redis-pub-sub,这不符合要求。
然后尝试TCP套接字,这是更好的,但仍然不是最好的。
所以我们切换到UDP数据报,这是更快。
这里是代码回购,只是几行代码。 https://github.com/SGF-Games/node-udpcomm