![](/img/trans.png)
[英]NodeJS - Send multiple requests and process all responses in one callback
[英]How can zmq (zeromq) be used to send multiple requests and route async responses between two NodeJS servers?
我有一個NodeJS API Web服務器(稱為WS1),該服務器從客戶端接收RESTful HTTP請求,並響應需要首先查詢其他本地服務器(稱為WS2)的需求。
流程非常像這樣:
到目前為止,WS1和WS2之間的所有通信都是通過HTTP請求完成的,因為兩台機器位於同一本地網絡上。
為了加快速度,盡管我正在考慮開始使用zmq 。 我查看了它們在文檔上顯示的模式,但仍然沒有發現並發問題。
WS1每秒可以向WS2發送許多請求,並且不能保證WS2以與接收請求相同的順序進行答復,因為某些異步操作在內部可能要比其他操作花費更長的時間。
因此,將zmq與NodeJS一起使用時,如何確保WS1從WS2收到消息時知道它屬於哪個原始客戶端請求? 有內置的機制可以處理嗎?
謝謝!
0MQ是一個有趣的工具集,可幫助抽象套接字通信。 有一些機制(應該選擇正確的套接字類型)可以使服務器響應正確的客戶端,並且可以在0mq的范圍內進行處理。
基本的API類型是:
如果您希望一台計算機能夠響應原始發件人,那么我認為您希望使用REQ-REP api類型。
那么您需要考慮每邊的多路復用,以使連接器正確。 但是首先為了簡單起見,將其一對一地保留:
示例客戶端(來自http://zguide.zeromq.org/js:rrclient
// Hello World client in Node.js
// Connects REQ socket to tcp://localhost:5559
// Sends "Hello" to server, expects "World" back
var zmq = require('zmq')
, requester = zmq.socket('req');
requester.connect('tcp://localhost:5559');
var replyNbr = 0;
requester.on('message', function(msg) {
console.log('got reply', replyNbr, msg.toString());
replyNbr += 1;
});
for (var i = 0; i < 10; ++i) {
requester.send("Hello");
}
示例服務器(來自http://zguide.zeromq.org/js:rrserver )
// Hello World server in Node.js
// Connects REP socket to tcp://*:5560
// Expects "Hello" from client, replies with "World"
var zmq = require('zmq')
, responder = zmq.socket('rep');
responder.connect('tcp://localhost:5560');
responder.on('message', function(msg) {
console.log('received request:', msg.toString());
setTimeout(function() {
responder.send("World");
}, 1000);
});
0MQ自動處理將答復路由回客戶端的過程。 它是消息的一部分(盡管我不記得您是否在這些示例中看到了地址緩沖區-可能已經抽象掉了)。 請求信封如下所示:
它是第一幀,它使0MQ能夠回復正確的客戶端。
一旦運行,則可以考慮1 .. * * .. 1和..。 它真正要做的就是要求您在適當的地方將套接字類型更改為DEALER和ROUTER。
我最終實現了某種“中間件”來支持zmq的此功能。
在下面的示例中,為簡單起見,我將Express與Node > = v4.0.0一起使用(支持本機JS Promise),但是顯然您可以將其替換為您喜歡的任何HTTP服務器(這些天我更喜歡Koa )和Promise庫。 這是兩個服務器的代碼。
var zmq = require('zmq');
var mem = {};
var requester = zmq.socket('req');
requester.on("message", function(reply) {
reply = reply.toString().split('*');
mem[reply.pop()](reply);
});
requester.connect("tcp://localhost:5555");
var app = require('express')();
app.get('/', function (req, res) {
var id = Date.now() + Math.random();
new Promise(function (resolve, reject) {
mem[id] = function (reply) {
reply[0] === 'success' ? resolve(reply[1]) : reject(reply[1]);
}
})
.then(function (data) {
res.send(data);
})
.catch(function (err) {
console.log(err);
res.send(500);
})
requester.send(id + '*' + message);
});
var server = app.listen(3000);
var zmq = require('zmq');
var responder = zmq.socket('rep');
responder.on('message', function(message) {
message = message.split('*');
var reqId = message[0];
// Do whatever async stuff you need with message[1]
// Then at the end of your callbacks you'll have something like this
if (err) {
responder.send('err' + '*' + JSON.stringify(err) + '*' + reqId);
} else {
responder.send('success' + '*' + JSON.stringify(yourData) + '*' + reqId);
}
});
responder.bind('tcp://*:5555');
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.