我們有幾個node.js進程應該能夠傳遞消息, 這樣做的最有效的方法是什麼? 如何使用node_redis的pub/sub什麼是最高效的node.js進程間通信庫/方法?
編輯:的進程可能在不同的機器
我們有幾個node.js進程應該能夠傳遞消息, 這樣做的最有效的方法是什麼? 如何使用node_redis的pub/sub什麼是最高效的node.js進程間通信庫/方法?
編輯:的進程可能在不同的機器
運行,我會用內置的功能,節點提供啓動。
可以使用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);
}
-1:「這些進程可能運行在不同的機器上」。節點在一個進程和他們的子進程之間有一個內置的通道,同一臺機器。 OP需要傳送來自不同機器的2個不同的進程。 –
如果你想從一臺機器發送消息到另一臺機器,而不關心回調,那麼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,如果您需要全面的雙向通信,請調查另一種解決方案。
很好的回答。我只是擔心'json.parse'和'json.stringify'的性能問題。我正在爲我的遊戲服務器使用nodejs,並且正在使用3個,4個甚至更多的節點實例與Redis進行通信(這樣我就可以進行水平縮放) - 並且這是一個我正在開發的aRPG遊戲,例如攻擊一個暴民,移動,所有這些東西都會非常繁忙。它還會好嗎?或者我現在在邊界線preMatureOptimization思考?謝謝 –
爲什麼不爲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的):
這需要幾年才能建立。而且難以維護。除了node.js之外,它只有一個節點包裝器,這使得修復問題變得更加困難 – Azarus
我們爲w在多進程節點應用程序上運行,這是處理大量實時跨進程消息所必需的。
我們首先嚐試了redis-pub-sub,這不符合要求。
然後嘗試TCP套接字,這是更好的,但仍然不是最好的。
所以我們切換到UDP數據報,這是更快。
這裏是代碼回購,只是幾行代碼。 https://github.com/SGF-Games/node-udpcomm
messenger的聲明它支持pub/sub有點誇張:每個訂閱者都必須訂閱不同的TCP端口,而發佈者必須知道所有這些端口。打敗pub/sub的目的。 –
提問後超過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替代舊的解決方案。也許我會在我完成了一些更多的信息後,擴大我的答案,這個模塊是如何工作的。
您對node-ipc的體驗如何? – shashi
@shashi,我一小時前開始和node-ipc一起玩,可以說它很棒。我發現通過unix套接字可以很容易地設置兩個節點進程相互通信。 – higginsrob
@higginsrob是的,我開始使用它,直到現在它令人印象深刻! – shashi
無,我想了解我應該嘗試什麼。常見的可能性有哪些? – DuduAlul
TCP,UDP,UNIX套接字 – generalhenry
好吧,我正在尋找一個庫,redis(pub/sub)如何? – DuduAlul