Использование node.js для постановки процессов в очередь, чтобы одновременно выполнялся только один процесс

Я пытаюсь написать 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 одновременно. Слишком много одновременных процессов приведет к перегрузке сервера.

Вместо этого я хочу, чтобы одновременно выполнялся только один такой процесс. Как я могу это сделать?


person rlandster    schedule 01.03.2012    source источник


Ответы (1)


Я думаю, что лучше всего использовать что-то вроде очереди заданий для выполнения этой задачи. Для этого отлично подходит 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 При обратном вызове для exec, если есть какие-либо ожидающие задачи (queue.length> 0), одна задача удаляется из очереди и выполняется.

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

person JP Richardson    schedule 01.03.2012
comment
Я бы не хотел дожидаться завершения работы, чтобы завершить HTTP-сеанс с клиентом: клиент отправляет задание, уходит и просто надеется, что работа будет выполнена. - person rlandster; 02.03.2012
comment
Алгоритм, который вы показываете, не совсем то, что я имел в виду: я бы хотел, чтобы все задачи в очереди выполнялись последовательно, даже если бы больше не было веб-запросов. Вместо того, чтобы писать код с нуля, я надеялся, что в node.js есть что-то, что упростит эту задачу. - person rlandster; 04.03.2012
comment
В Node.js нет ничего, что могло бы делать то, что вы хотите. Однако есть сторонние инструменты / библиотеки, которые будут. Куэ - один из них и хорошо отвечает вашим требованиям, если только я не понял ваши требования или вы неправильно их поняли. - person JP Richardson; 05.03.2012
comment
Да, и алгоритм, который я представил, будет нормально работать без каких-либо дополнительных HTTP-запросов. Он также делает их serial способом, как вы просили. По общему признанию, здесь и там может быть опечатка, но концепция правильная. - person JP Richardson; 05.03.2012