【问题标题】:Using node.js to queue processes so that only one process runs at a time使用 node.js 对进程进行排队,以便一次只运行一个进程
【发布时间】:2012-03-19 15:34:53
【问题描述】:

我正在尝试编写基于 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 的进程。太多同时处理的进程会使服务器不堪重负。

相反,我只想同时运行一个这样的进程。我该怎么做?

【问题讨论】:

    标签: node.js fork nonblocking


    【解决方案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. 如果队列不为空,则任务入队。 4 如果有任何挂起的任务 (queue.length > 0),则在回调到 exec 时,一项任务被出列并被执行。

    这有意义吗?

    【讨论】:

    • 我不想等到作业完成后再完成与客户端的 HTTP 会话:客户端提交作业,然后离开,只希望作业完成。
    • 您展示的算法与我的想法并不完全一致:即使没有更多的 Web 请求,我也希望所有排队的任务都连续运行。我希望不是从头开始编码,而是希望 node.js 有一些内置的东西可以让这变得简单。
    • Node.js 没有原生内置的东西来做你想做的事。但是,有第三方工具/库可以。 Kue 就是其中之一,并且很好地满足了您的要求,除非我误解了您的要求或您误解了它们。
    • 哦,我提出的算法无需任何额外的 HTTP 请求就可以正常工作。它还按照您的要求以serial 的方式进行操作。诚然,这里和那里可能存在拼写错误,但这个概念是合理的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-20
    • 2020-09-04
    相关资源
    最近更新 更多