У меня есть асинхронная операция, которая делегируется рабочему процессу.
Поскольку каждая операция занимает примерно 2 секунды, я хотел передать результат этой операции в ответ на запрос.
Я завернул выполнение рабочего процесса в обещание, которое не разрешается до тех пор, пока рабочий процесс не завершит работу с интенсивным использованием ЦП и вернет результат:
module.exports = (req, res, controller) => {
res.setHeader('Content-Type', 'application/json');
const workerService = controller.services.workers;
if (!workerService) {
return res.json({
ok: false,
info: 'Worker service has not been started. Relaunch API server and check logs.'
});
}
let commandObject = '';
try {
const postBody = req.body;
// build a backtest execution command based on request params
commandObject = getWorkerCommandFromPostBody(postBody);
} catch (exception) {
return res.json({
ok: false,
info: exception
});
}
return controller.services.workers
.promiseWorkerExecution(commandObject)
.then(result => {
if (result.context && result.context.results) {
return res.end(result.context.results);
}
return res.end(result);
})
.catch(e => res.end(e));
}
Здесь я запутался. Основной поток, в котором выполняется мой экспресс-процесс, не блокируется. Вся интенсивная операция делегируется выделенному подпроцессу (через модуль «кластер»).
Однако, если я инициирую 3 из этих запросов, 2-й запрос даже не начнет обрабатываться, пока первый запрос не увидит res.end()
. Это просто ожидание обещания решить. Я уверен, что это может быть воспроизведено с обещанием, ожидающим, пока setTimeout разрешится через несколько секунд.
Это ожидается? Я думал, что мог бы просто рассматривать это как асинхронные операции, и когда я буду готов, этот ответ на запрос может быть отправлен, когда обещание разрешится.
Нет ли способа продолжить прием параллельных запросов на экспресс-сервер, не выполняя также кластер на экспресс-сервере? Я надеялся, что один экспресс-сервер и отдельные (ограниченные) работники будут делегировать / обрабатывать нагрузку на процессор.
Мне нужно отслеживать, сколько операций выполняется параллельно, поэтому я хотел, чтобы в идеале не было отдельных экспресс-служб ... У кого-нибудь есть рекомендации по обработке этого?
Редактировать: я должен добавить, что я знаю об однопоточной природе Node, но я думал, что факт обещания разрешает параллельные асинхронные операции, пока они не блокируют поток ...
Редактировать: я воспроизвел проблему в песочнице, используя только setTimeout для задержки res.send:
Привет всем, так что его можно воспроизвести с помощью setTimeout, который явно не требует интенсивной блокировки процессора. Песочница:
https://codesandbox.io/embed/nr41lkw95j
Я тестирую 3 параллельных запроса, вызывая это в терминале:
curl https://nr41lkw95j.sse.codesandbox.io/test && curl https://nr41lkw95j.sse.codesandbox.io/test && curl https://nr41lkw95j.sse.codesandbox.io/test
Терминал на сервере песочницы показывает, что он блокирует обработку запроса, пока текущий запрос не отправит ответ, даже если что-то происходит в асинхронном обратном вызове