Node.js/Экспресс и параллельные очереди

Мы создаем инфраструктуру, в которой есть сервер Node.js и Express.

На сервере происходит следующее:

  • Сервер принимает входящий HTTP-запрос от клиента.
  • Сервер генерирует два файла (эта операция может быть "относительно длинной", что означает также 0,1 секунды или около того)
  • Сервер загружает сгенерированные файлы (~ 20-200 КБ каждый) на внешний CDN
  • Сервер отвечает клиенту, и это включает в себя URI файла на CDN

В настоящее время сервер делает это последовательно для каждого запроса, и это работает достаточно хорошо (Node/Express может обрабатывать параллельные запросы автоматически). Однако, поскольку мы планируем расти, количество одновременных запросов может расти выше, и мы считаем, что нам лучше реализовать очередь для обработки запросов. В противном случае мы можем столкнуться с слишком большим количеством задач, запущенных одновременно, и слишком много открытых подключений к CDN. Быстрое реагирование на клиента не является релевантным.

То, о чем я думал, состоит в том, чтобы иметь отдельную часть на сервере Node, которая содержит несколько "рабочих" (2-3, но мы будем проводить тесты для определения правильного количества одновременных операций). Итак, новый поток будет выглядеть примерно так:

  • После принятия запроса от клиента сервер добавляет операцию в очередь.
  • Есть 2-3 (для тестирования) работников, которые берут элементы из очереди и выполняют все операции (генерируют файлы и загружают их в CDN).
  • Когда рабочий обработал операцию (не имеет значения, останется ли она в очереди в течение относительно длительного времени), он уведомляет сервер Node (обратный вызов), и сервер отвечает клиенту (который имеет ожидали в то же время).

Что вы думаете об этом подходе? Вы считаете, что это правильный?

В основном важно, КАК это может быть реализовано в Node/Express?

Спасибо за ваше время

Ответ 1

(Отвечая на мой собственный вопрос)

В соответствии с этот вопрос о переполнении стека решение в моем случае было бы реализовать очередь, используя Асинхронный модуль Caolan McMahon.

Основное приложение будет создавать задания и вставлять их в очередь, которая имеет ограничение на количество одновременных заданий, которые могут выполняться. Это позволяет обрабатывать задачи одновременно, но с жестким контролем над лимитом. Он работает как Cocoa NSOperationQueue на Mac OSX.

Ответ 2

TL;DR; Вы можете использовать собственный Node.js модуль кластера для обработки множества параллельных запросов.

Некоторая преамбула: Node.js per se однопоточная. Его Event Loop - это то, что делает его превосходным для обработки нескольких запросов одновременно, даже в модели с одним потоком, что является одной из лучших возможностей IMO.

Реальная сделка: Итак, как мы можем масштабировать это, чтобы обрабатывать больше параллельных соединений и использовать все доступные процессоры? С помощью кластерного модуля.

Этот модуль будет работать точно так же, как указано в @Qualcuno, что позволит вам создать нескольких рабочих (например, процесс) за мастером для совместного использования нагрузки и более эффективно использовать доступные процессоры.

Согласно официальной документации Node.js:

Поскольку рабочие - это все отдельные процессы, их можно убить или повторно создаются в зависимости от потребностей вашей программы, не влияя на другие работников. До тех пор, пока некоторые рабочие еще живы, сервер будет продолжать принимать соединения.

Необходимый пример:

var cluster = require('cluster');
var http = require('http');
var numCPUs = require('os').cpus().length;

if (cluster.isMaster) {
  // Fork workers.
  for (var i = 0; i < numCPUs; i++) {
    cluster.fork();
  }

  cluster.on('exit', function(worker, code, signal) {
    console.log('worker ' + worker.process.pid + ' died');
  });
} else {
  // Workers can share any TCP connection
  // In this case its a HTTP server
  http.createServer(function(req, res) {
    res.writeHead(200);
    res.end("hello world\n");
  }).listen(8000);
}

Надеюсь, это то, что вам нужно.

Комментарий, если у вас есть дополнительные вопросы.

Ответ 3

Чтобы сделать это, я бы использовал структуру, подобную той, которую Heroku предоставляет с помощью Web/Worker Dynos (серверов). Веб-серверы могут принимать запросы и передавать информацию работникам, которые могут выполнять обработку и загрузку информации. Я хотел бы, чтобы внешний интерфейс прослушивал сокет (socket.io) для URL-адреса внешнего CDN, который будет запущен у рабочего, когда загрузка будет закончена. Надеюсь, это имеет смысл.

Ответ 4

Вы можете использовать модуль Kue с Redis (база данных для хранения заданий). Резервное копирование очереди. вы создаете задания и размещаете их в модуле kue, и вы можете указать, сколько из них будет работать над ними. Полезные ссылки: kue - https://github.com/Automattic/kue