2011-06-24 85 views

回答

4

运行,我会用内置的功能,节点提供启动。
可以使用process signalling像:

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

此信令

当进程接收到一个信号触发。对于如SIGINT,SIGUSR1等

标准POSIX信号名称的 列表,请参阅的sigaction(2)一旦你了解的过程,你可以spwn一个child-process,并把它挂到了message事件以检索和发送消息。当使用child_process.fork()时,您可以使用child.send(message, [sendHandle])给孩子写信,并通过孩子上的“消息”事件接收消息。您也可以使用cluster。群集模块允许您轻松创建全部共享服务器端口的进程网络。

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

+0

-1:“这些进程可能运行在不同的机器上”。节点在一个进程和他们的子进程之间有一个内置的通道,同一台机器。 OP需要传送来自不同机器的2个不同的进程。 –

34

如果你想从一台机器发送消息到另一台机器,而不关心回调,那么Redis pub/sub是最好的解决方案。这很容易实现,而且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)); 
}; 

如果你想发送不同类型的消息,你可以使用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)); 
}; 

最好的做法是通过其功能命名您的流程(或机器)(例如'send_email')。在这种情况下,如果过程(或机器)实现多个功能,则可以订阅多个频道。

实际上,可以使用redis建立双向通信。但它更棘手,因为它需要为每个消息添加唯一的回叫通道名称,以便接收回调而不会丢失上下文。

所以,我的结论是这样的:如果您需要“发送和忘记”通信,请使用Redis,如果您需要全面的双向通信,请调查另一种解决方案

+0

很好的回答。我只是担心'json.parse'和'json.stringify'的性能问题。我正在为我的游戏服务器使用nodejs,并且正在使用3个,4个甚至更多的节点实例与Redis进行通信(这样我就可以进行水平缩放) - 并且这是一个我正在开发的aRPG游戏,例如攻击一个暴民,移动,所有这些东西都会非常繁忙。它还会好吗?或者我现在在边界线preMatureOptimization思考?谢谢 –

29

为什么不为IPC使用ZeroMQ/0mq? Redis(一个数据库)因为像IPC这样简单的事情而被杀死。

引用手册:

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

使用0MQ(甚至通过节点核心网库中的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(上述模块的叉这支持PUBLISHER侧滤波PubSub的):

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

+0

这需要几年才能建立。而且难以维护。除了node.js之外,它只有一个节点包装器,这使得修复问题变得更加困难 – Azarus

1

我们为w在多进程节点应用程序上运行,这是处理大量实时跨进程消息所必需的。

我们首先尝试了redis-pub-sub,这不符合要求。

然后尝试TCP套接字,这是更好的,但仍然不是最好的。

所以我们切换到UDP数据报,这是更快。

这里是代码回购,只是几行代码。 https://github.com/SGF-Games/node-udpcomm

2

看一看节点信使

https://github.com/weixiyen/messenger.js

将适合大部分的需求轻松(发布/订阅...射后不理..发送/请求)具有自动保持连接池

+0

messenger的声明它支持pub/sub有点夸张:每个订阅者都必须订阅不同的TCP端口,而发布者必须知道所有这些端口。打败pub/sub的目的。 –

23

提问后超过4年,有一个名为node-ipc的进程间通信模块。它支持在同一台机器以及TCP,TLS和UDP上进行通信的unix/windows套接字,声称至少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替代旧的解决方案。也许我会在我完成了一些更多的信息后,扩大我的答案,这个模块是如何工作的。

+0

您对node-ipc的体验如何? – shashi

+1

@shashi,我一小时前开始和node-ipc一起玩,可以说它很棒。我发现通过unix套接字可以很容易地设置两个节点进程相互通信。 – higginsrob

+0

@higginsrob是的,我开始使用它,直到现在它令人印象深刻! – shashi

相关问题