Использование node.js для постановки в очередь процессов, так что одновременно запускается только один процесс - PullRequest
0 голосов
/ 01 марта 2012

Я пытаюсь написать http-сервер на базе node.js, который отвечает на запросы об обновлении записей клиента. Эти запросы просят сервер выполнить работу на стороне сервера, но для выполнения запроса не нужно ждать завершения работы на стороне сервера.

Мой код выглядит так:

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 Ответ

1 голос
/ 01 марта 2012

Я думаю, что вам лучше всего использовать что-то вроде Job Queue для выполнения этой задачи. Kue отлично подходит для этого. По сути, вы должны поставить работу в очередь, и, используя «завершенный» метод, вы отправите ответ HTTP. Kue также позволяет создавать количество рабочих процессов. Проверьте это.

Edit:

Вам не нужно ждать, пока работа не будет завершена. Вы все еще можете ответить раньше. По сути, независимо от того, используете ли вы массив 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. Если очередь пуста, длинное задание выполняется exec'd.
  3. Если очередь не пуста, задача ставится в очередь. 4 При обратном вызове exec, если есть какие-либо ожидающие задачи (queue.length> 0), одна задача снимается с очереди и выполняется exec'd.

Имеет ли это смысл?

...