我有一个NodeJS API Web服务器(让我们称之为WS1)从客户端接收RESTful HTTP请求,并响应需要首先查询另一个本地服务器(让我们称之为WS2)。
流程非常类似:
到目前为止,WS1和WS2之间的所有通信都是通过HTTP请求完成的,因为这两台计算机位于同一本地网络上。
为了加快速度,我正在考虑开始使用zmq。我查看了他们在文档中显示的模式,但仍未找出并发问题。
WS1每秒可以向WS2发送许多请求,并且无法保证WS2以与接收请求相同的顺序进行回复,因为某些异步操作在内部可能需要比其他操作更长的时间。
因此,将zmq与NodeJS一起使用,如何确保当WS1从WS2收到消息时,它知道它属于哪个原始客户端请求?是否有内置的机制来处理它?</ p>
谢谢!
答案 0 :(得分:3)
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。
答案 1 :(得分:1)
我最终实现了某种&#34;中间件&#34;使用zmq支持此功能。
在下面的示例中为简单起见,我已将Express与Node&gt; = v4.0.0(支持本机JS承诺)一起使用,但您显然可以将其替换为任何HTTP服务器喜欢(这些天我更喜欢Koa)并承诺你喜欢的图书馆。这是两台服务器的代码。
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');