ioSocket не излучает браузер на сервере с большой нагрузкой
Некоторые запросы, которые могут быть отправлены на мой сервер nodejs, требуют интенсивной обработки (например, 5000 файлов). Поскольку обработка запроса займет некоторое время, я хочу отображать прогресс в браузере. Для этого я использую io-сокет. Регулярно сервер отправляет клиенту прогресс, например, ioSocket.emit("log", "progress 24%)
,
Однако, если отправка прогресса клиенту обычно работает, когда имеется большое количество файлов, это не так. Ничего не отправлено в браузер.
Я уверен, что процесс идет хорошо, так как я регистрирую прогресс на терминале узла, и там он выглядит как ожидалось.
Мне интересно, что я могу сделать, чтобы событие ioSocket.emit работало в случае большой нагрузки, потому что именно там наиболее полезно видеть прогресс.
Функция обработки файлов выглядит следующим образом:
var child_process = require("child_process");
function (ioSocket) {
ioSocket.emit("log", "start")
var ratingCounts = 0;
var listOfFilesRatings = []
_.each(listOfFilesPaths, function(path, i){
child_process.exec("exiftool -b -Rating "+ path, function(err, stdout){
if (err) console.log(err)
else {
listOfFilesRatings.push(stdout);
ratingCounts++;
ioSocket.emit("log", "rating test progress "+ ratingCounts)
};
});
ioSocket.emit("log", "each progress "+ i)
});
}
В этом примере только первый "стартовый" emit будет запущен в браузере.
Однако, если я сделаю следующее:
function (ioSocket) {
ioSocket.emit("log", "start")
for (i=0; i<1000; i++) {
ioSocket.emit("log", "each progress "+ i)
};
}
все работает отлично, и я получаю "начало" и все "каждый прогресс" отправляется в браузер.
1 ответ
Если вы обрабатываете 5000 файлов, ваша схема с _.each()
а также child_process.exec()
запустит 5000 процессов exiftool одновременно. Это, скорее всего, поставит любой компьютер, за исключением, возможно, большого железа на колени. Вероятно, вам следует запускать не более N из них в то время, когда вы запускаете некоторые тесты производительности на вашем конкретном оборудовании, чтобы определить, каким должно быть N (вероятно, меньше 10).
Вот один из способов сделать это:
var child_process = require("child_process");
function processFiles(ioSocket) {
return new Promise((resolve, reject) => {
ioSocket.emit("log", "start")
let ratingCounts = 0;
let listOfFilesRatings = [];
const maxInFlight = 10;
let inFlightCntr = 0;
let fileIndex = 0;
function run() {
// while room to run more, run them
while (inFlightCntr < maxInFlight && fileIndex < listOfFilesPaths.length) {
let index = fileIndex++;
++inFlightCntr;
ioSocket.emit("log", "each progress " + index)
child_process.exec("exiftool -b -Rating " + path, function(err, stdout) {
++ratingCounts;
--inFlightCntr;
if (err) {
console.log(err);
listOfFilesRatings[index] = 0;
} else {
listOfFilesRatings[index] = stdout;
ioSocket.emit("log", "rating test progress " + ratingCounts)
}
run();
});
}
if (inFlightCntr === 0 && fileIndex >= listOfFilesPaths.length) {
// all done here
console.log(listOfFilesRatings);
resolve(listOfFilesRatings);
}
}
run();
});
}
processFiles().then(results => {
console.log(results);
});