使用node.js对进程进行排队,以便一次只运行一个进程

时间:2012-03-01 05:37:12

标签: node.js fork nonblocking

我正在尝试编写基于node.js的http服务器来响应更新客户端记录的请求。这些请求要求服务器在服务器端执行操作,但请求不需要等待服务器端的工作完成。

我的代码如下所示:

var http = require('http');
http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  var sys    = require('util'),
      exec   = require('child_process').exec,
      child;

  var parsed_url = require('url').parse(request.url, true) ;
  var query = parsed_url['query'] ;
  var client_id = query['client_id'] ;

  child = exec('some_tedious_server_side_calculation ' + client_id,
               function (error, stdout, stderr) {
               if (error !== null) {
                 console.log('exec error: ' + error);
               }
  });
  response.end('I will process ' + client_id + ' when I get around to it\n');
}).listen(8888);

console.log('Server running at http://127.0.0.1:8888/');

这样可行,但由于exec是非阻塞的,如果我一下子收到大量请求,我将同时获得大量进程some_tedious_server_side_calculation。同时进程太多会使服务器崩溃。

相反,我希望只有一个这样的进程可以同时运行。我怎么能这样做?

1 个答案:

答案 0 :(得分:1)

我认为最好的办法是使用像Job Queue这样的东西来完成这项任务。 Kue对此非常有用。基本上你要做的就是排队工作和工作的'完整'方法,你会发回HTTP响应。 Kue还允许您创建工作进程数。看看吧。

编辑:

您无需等到作业完成。你以前仍然可以回复。实质上,无论您使用Kue还是JavaScript数组(充当队列),都可以这样做。

var myQueue = [];
childCallback = function (error, stdout, stderr) {
      if (error !== null) {
        console.log('exec error: ' + error);
      }

      if (myQueue.length > 0) {
        var cid = myQueue.shift();
        child = exec('some_tedious_server_side_calculation ' + clid, childCallback);     
      }                  
}

var http = require('http');
http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  var sys    = require('util'),
      exec   = require('child_process').exec,
      child;

  var parsed_url = require('url').parse(request.url, true) ;
  var query = parsed_url['query'] ;
  var client_id = query['client_id'] ;

  if (myQueue.length === 0) {
      child = exec('some_tedious_server_side_calculation ' + client_id, childCallback);               
  } else {
    myQueue.push(client_id); //something like this... maybe the actual command? 
  }

  });
  response.end('I will process ' + client_id + ' when I get around to it\n');
}).listen(8888);

console.log('Server running at http://127.0.0.1:8888/');

好的,我修改了代码,以便您可以看到它的工作原理。以下是重要的修改:

  • 我正在使用数组作为队列。
  • 我已经为exec取出了匿名回调函数。

简而言之,它的工作原理如下:

  1. 您收到了HTTP请求。
  2. 如果队列为空,则执行长任务。
  3. 如果queue不为空,则任务将排队。 4在exec的回调中,如果有任何挂起的任务(queue.length> 0),则一个任务出列并执行。
  4. 这有意义吗?