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

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

На сервере происходит то, что происходит:

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

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

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

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

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

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

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

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

Некоторые преамбулы: Node.js per se однопоточно. Его Event Loop – это то, что делает его превосходным для обработки нескольких запросов одновременно, даже в модели с одним streamом, что является одной из лучших функций 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); } 

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

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

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

В соответствии с этим вопросом в Stack Overflow решение в моем случае было бы реализовать очередь с использованием асинхронного модуля Caolan McMahon .

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

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

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