簡體   English   中英

zmq(zeromq)如何用於在兩個NodeJS服務器之間發送多個請求並路由異步響應?

[英]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)的需求。

流程非常像這樣:

  1. WS1從客戶端接收HTTP請求並對其進行解析。
  2. WS1向WS2發送請求以獲取一些信息。
  3. 當WS1從WS2收到響應時,它將完成對原始請求的處理,並將響應發送回客戶端。

到目前為止,WS1和WS2之間的所有通信都是通過HTTP請求完成的,因為兩台機器位於同一本地網絡上。

為了加快速度,盡管我正在考慮開始使用zmq 我查看了它們在文檔上顯示的模式,但仍然沒有發現並發問題。

WS1每秒可以向WS2發送許多請求,並且不能保證WS2以與接收請求相同的順序進行答復,因為某些異步操作在內部可能要比其他操作花費更長的時間。

因此,將zmq與NodeJS一起使用時,如何確保WS1從WS2收到消息時知道它屬於哪個原始客戶端請求? 有內置的機制可以處理嗎?

謝謝!

0MQ是一個有趣的工具集,可幫助抽象套接字通信。 有一些機制(應該選擇正確的套接字類型)可以使服務器響應正確的客戶端,並且可以在0mq的范圍內進行處理。

基本的API類型是:

  1. 推拉
  2. PUB-SUB
  3. 請求 - 應答

如果您希望一台計算機能夠響應原始發件人,那么我認為您希望使用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的此功能。

在下面的示例中,為簡單起見,我將ExpressNode > = v4.0.0一起使用(支持本機JS Promise),但是顯然您可以將其替換為您喜歡的任何HTTP服務器(這些天我更喜歡Koa )和Promise庫。 這是兩個服務器的代碼。

WS1(請求者)

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);

WS2(響應者)

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM