长轮询和队列来保存请求

时间:2013-06-10 10:02:46

标签: node.js mongodb long-polling

POST /add-request - 添加新请求

POST /get-request - 返回第一个(最旧的)请求

我有很多被称为“奴隶”的Java应用程序。他们的工作是调用POST /get-request来获取处理请求,并在处理后将其保存到数据库。所有请求都存储在mongoDB中。 /add-request只是向db添加请求。 /get-request使用findAndModify mongo查询从队列获取第一个请求并将其状态设置为“正在处理”(当从DB请求两次相同请求时,需要此状态以避免出现这种情况)。现在奴隶只需每2秒调用一次api。但我想在这里使用一些长轮询。它应该是这样的:

  1. 我必须将奴隶请求保留在队列中。
  2. 如果没有新请求,我必须在4秒后设置超时foreach slave请求发送例如404.
  3. 当通过/add-request添加新请求时,我必须从队列中获取第一个slave请求,将其从此队列中删除,从DB获取请求并将其发送给此slave。
  4. 所以让我说我必须处理(我正在使用快递):

    function addRequest(req,res,next){ 
        // add request to db and check if there is waiting slave request in queue
        // if there is one remove it from queue, clear timeout on it, get request from db
        // and send it to slave
    }
    
    function getRequest(req,res,next){ 
        // get request from db - if there is no request add this slave request to queue
        // set timeout to send 404 after 4 seconds
    }
    

    问题在于队列 - 我尝试了很多qpproaches,但没有任何“同步”,我无法使其工作......当两个快速处理程序在其上运行时,是否有可能确保队列的一致性同一时间?问题是在超时后从队列中删除请求。我必须使用一些uid在队列中搜索请求,然后将其删除...

    也许有一些图书馆/工具可以实现我的目标?


    当没有请求从属进程处理时,返回

    404。 我希望奴隶尽快获得新请求 - 所以如果我立即返回响应(新请求或404没有请求时),那么每个奴隶都必须不停地调用api并且它会产生影响关于服务器性能我认为。所以我希望每个从服务器在服务器上“保持”4秒钟,然后返回任何数据。

1 个答案:

答案 0 :(得分:1)

有趣的技术,以确保您尽快处理排队的请求。

在同步队列方面,没有必要因为Node是单线程的。您不必担心Java中的多线程问题,我认为这非常好。

这是一些可能有用的粗略代码。添加错误处理和正确的Mongo数据库调用。

var queue = {};

function addJob(req,res,next){ 
  var job = req.body;
  mongo.add(job, function(err){ // pseudo code to add request to db. 
    res.send(200); // request is stored, no need to keep the client waiting.
    // find a random slave in the queue:
    for(var slaveName in queue) {
      queue[slaveName].send(job);
      delete queue[slaveName];
      break;
    }      
  });
}

function getRequest(req,res,next){ 
  // get request from db - if there is no request add this slave request to queue
  mongo.get(..., function(err, job){
    if(job){
      return res.send(job);
    }
    // no job, add slave to queue:
    var slaveName = req.body;
    queue[slaveName] = res;

    // set timeout to send 404 after 4 seconds
    setTimeout(function(){
      delete queue[slaveName];
      res.send(404);
    }, 4000);
  }
}