io Socket 在服务器负载过重时不发送到浏览器
ioSocket not emitting to browser on server heavy load
可以向我的 nodejs 服务器发出的一些请求需要大量处理(例如:5000 个文件)。由于请求需要一段时间才能处理,我想在浏览器中显示进度。为此,我正在使用 io-socket。服务器定期将进度提前发送给客户端,例如 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)
});
}
在这个例子中,只有第一个 "start" emit 会被触发到浏览器。
但是,如果我执行以下操作:
function (ioSocket) {
ioSocket.emit("log", "start")
for (i=0; i<1000; i++) {
ioSocket.emit("log", "each progress "+ i)
};
}
一切正常,我收到 "start" 和所有 "each progress" 发送到浏览器。
如果您正在处理 5000 个文件,您的 _.each()
和 child_process.exec()
方案将立即启动 5000 个 exiftool 进程。这可能会让任何计算机都崩溃,除了一些大铁。在你 运行 对你的特定硬件进行一些性能测试以确定 N 应该是多少(可能小于 10)的时候,你可能应该启动不超过 N 个。
这是一种方法:
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);
});
可以向我的 nodejs 服务器发出的一些请求需要大量处理(例如:5000 个文件)。由于请求需要一段时间才能处理,我想在浏览器中显示进度。为此,我正在使用 io-socket。服务器定期将进度提前发送给客户端,例如 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)
});
}
在这个例子中,只有第一个 "start" emit 会被触发到浏览器。
但是,如果我执行以下操作:
function (ioSocket) {
ioSocket.emit("log", "start")
for (i=0; i<1000; i++) {
ioSocket.emit("log", "each progress "+ i)
};
}
一切正常,我收到 "start" 和所有 "each progress" 发送到浏览器。
如果您正在处理 5000 个文件,您的 _.each()
和 child_process.exec()
方案将立即启动 5000 个 exiftool 进程。这可能会让任何计算机都崩溃,除了一些大铁。在你 运行 对你的特定硬件进行一些性能测试以确定 N 应该是多少(可能小于 10)的时候,你可能应该启动不超过 N 个。
这是一种方法:
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);
});