我正在运行一个高速公路服务器,在该服务器中,端点init执行一些紧张的操作,平均完成时间为10秒。在这10秒内,主循环被“卡住”,因此不可能将请求发送到高速公路服务器。我已经在googling上搜索了一段时间,但是没有发现任何能够同时处理请求的快捷方式。如果这不可能的话,那就太傻了。对于任何暗示或帮助,我都非常感激。
示例代码:
routes.js
app.route('/v1/cv/random').get(init);特性/init.js
module.exports = async function init(req, res) {
try {
// perform some time consuming operation here
res.status(201).send(someVar);
} catch (err) {
res.status(500).send(`failed to init`).end();
}
};发布于 2022-07-18 12:55:45
可以以同步的方式实现长时间运行的算法,例如河内塔。
function move(from, to, via, n) {
if (n > 1)
move(from, via, to, n - 1);
to.unshift(from.shift());
if (n > 1)
move(via, to, from, n - 1);
}
app.get("/tower", function(req, res) {
var a = [];
for (var i = 0; i < Number(req.query.n); i++) a.push(i);
var b = [];
var c = [];
move(a, b, c, a.length);
res.end("Done");
});使用足够大的GET /tower?n=<N>调用<N>确实会阻塞express的主循环。
可以通过在算法中引入异步性来避免这种阻塞,例如使用setTimeout(nextAlgorithmicStep)命令。这将nextAlgorithmicStep函数放入队列中,但同一队列也有处理并发请求的函数的空间:
function tick(from, to, via, n) {
return new Promise(function(resolve, reject) {
setTimeout(function() {
move(from, to, via, n, resolve);
});
});
}
async function move(from, to, via, n, resolve) {
if (n > 1)
await tick(from, via, to, n - 1);
to.unshift(from.shift());
if (n > 1)
await tick(via, to, from, n - 1);
resolve();
}
app.get("/tower", async function(req, res) {
var a = [];
for (var i = 0; i < Number(req.query.n); i++) a.push(i);
var b = [];
var c = [];
await tick(a, b, c, a.length);
res.end("Done");
});这样,您可以等待(永远)请求GET /tower?n=64回来,但至少仍然可以向同一台服务器发出并发请求。(使用简单的Promise或process.nextTick代替setTimeout并不能“异步”到允许在两者之间处理并发请求。)
然而,在第一个版本中“立即”完成的GET /tower?n=10的执行现在要花费更长的时间。最好不是在递归的所有setTimeout级别上使用setTimeout,而是只在大约十分之一的级别上使用。您必须在RSA算法中找到类似的异步性优点。
这就是使用单线程Node.js程序可以做的事情。但是有一种选择是使用多Node.js过程。
app.get("/tower", function(req, res) {
spawn("node", ["tower.js", req.query.n]).stdout.pipe(res);
});其中tower.js是一个额外的Javascript程序:
function move(from, to, via, n) {
if (n > 1)
move(from, via, to, n - 1);
to.unshift(from.shift());
if (n > 1)
move(via, to, from, n - 1);
}
var a = [];
for (var i = 0; i < Number(process.argv[2]); i++) a.push(i);
var b = [];
var c = [];
move(a, b, c, a.length);
process.stdout.write("Done");发布于 2022-07-19 10:42:52
我在@Heiko en更新他的答案之前不久找到了一个答案。这(我认为)是一种类似的方法。
我找到了一种使用child_process的方法,通过使用
const {fork} = require('child_process');
...
module.exports = async function init(req, res) {
try {
const childProcess = fork('./path/to/the/script.js');
childProcess.send({'body': req.body});
childProcess.on('message', (message) => {
res.status(201).json({someVar: message}).end();
});
} catch (err) {
res.status(500).send(`failed to init`).end();
}
};script.js看起来就像
process.on('message', async (message) => {
// perform a time consuming operation here
process.send(someVar);
process.exit();
});https://stackoverflow.com/questions/73021181
复制相似问题