NodeJS事件发射器阻塞问题

时间:2016-01-27 17:29:05

标签: javascript node.js zeromq

我有一个节点应用程序使用此处的Node-ZMQ绑定处理来自另一个应用程序的一些ZeroMQ事件:https://github.com/JustinTulloss/zeromq.node

我遇到的问题是事件中的一个操作需要很长时间才能处理,这似乎阻止了在此期间处理任何其他事件。虽然应用程序当前没有群集,但这样做只会提供更多的线程,并没有真正解决问题。我想知道是否有一种方法允许这些异步调用在处理时不阻止其他传入请求,以及我如何实现它们。

这是我目前正在做的一个高度浓缩/人为的代码示例:

var zmq = require('zmq');
var zmqResponder = zmq.socket('rep');
var Client = require('node-rest-client').Client;
var client = new Client();

zmqResponder.on('message', function (msg, data) {
  var parsed = JSON.parse(msg);
  logging.info('ZMQ Request received: ' + parsed.event);
  switch (parsed.event) {
    case 'create':
        //Typically short running process, not an issue
    case 'update':
        //Long running process this is the issue
        serverRequest().then(function(response){
            zmqResponder.send(JSON.stringify(response));
        });
     }

});

function serverRequest(){
    var deferred = Q.defer();
      client.get(function (data, response) {
      if (response.statusCode !== 200) {
        deferred.reject(data.data);
      } else {
        deferred.resolve(data.data);
      }
  });
    return deferred.promise;
}

编辑**以下是代码的要点:https://gist.github.com/battlecow/cd0c2233e9f197ec0049

1 个答案:

答案 0 :(得分:1)

我认为,通过评论主题,我已经确定了您的问题。 REQ/REP具有严格的同步消息顺序保证...您必须接收 - 发送 - 接收 - 发送等。 REQ必须以发送方式开始,REP必须以接收方式开始。因此,您一次只处理一条消息,因为您选择的套接字类型强制执行该操作。

如果您使用的是其他非事件驱动的语言,那么当您尝试连续发送或接收两次但是节点时,您可能会收到错误消息,告诉您该怎么做错了允许您执行此操作,并将后续消息排队,直到它们按消息顺序轮流。

您希望将REQ/REP更改为DEALER/ROUTER,并且它会以您期望的方式运作。您必须稍微更改ROUTER套接字的逻辑才能使其正确发送,但其他所有内容都应该相同。

粗略的示例代码,使用已发布的要点的相关部分:

var zmqResponder = zmq.socket('router');

zmqResponder.on('message', function (msg, data) {
    var peer_id = msg[0];
    var parsed = JSON.parse(msg[1]);
    switch (parsed.event) {
        case 'create':
            // build parsedResponse, then...
            zmqResponder.send([peer_id, JSON.stringify(parsedResponse)]);
            break;
    }
});

zmqResponder.bind('tcp://*:5668', function (err) {
    if (err) {
        logging.error(err);
    } else {
        logging.info("ZMQ awaiting orders on port 5668");
    }
});

...你需要抓住peer_id(或者你想要称之为的任何东西,在ZMQ命名法中它是你发送的套接字的套接字ID,想一想作为来自您收到的邮件的第一帧的"地址"并使用它作为您发回的邮件的第一帧发送。

顺便说一句,我只是注意到你的要点是connect() - 和bind() - 在同一个套接字上(分别是zmq.js第52行和第143行)。不要这样做。从其他线索中推断出来,你只想在这个过程的这一边bind()