2011-06-24 87 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

相關問題