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