【发布时间】:2022-01-05 15:11:12
【问题描述】:
我有一个运行 Bull 和 express 的作业服务器。
服务器要求
接收包含对象的请求,并将该对象用作本地程序的输入(别无选择),该程序需要几分钟到几个小时才能运行。作业必须按照接收顺序一个接一个地运行(不能绕开这个)。
TL;DR 服务器:
// Set up Bull queue and process
const osmQueue = new Bull("osm", {
redis: {
port: "6969",
},
});
osmQueue.process((job) => {
extractOms(job);
});
// Process function
const extractOms = (job) => {
// I have tried execSync also
spawnSync("programme", [
"this",
"programme",
"takes",
"~30",
"minutes",
"to",
"run",
"and",
"requires",
"full",
"system",
"resources (cannot share system resources with another job)",
]);
return
};
// Express server with single route
const app = express();
app.post("/create-map-job", (req, res) => {
console.log("fired"); // Fires on first request. Blocked on second until job done
osmQueue.add(req.body);
res.send("job successfully queued"); // Returns on first request. Blocked on second until job done
});
app.listen(PORT, () => {
console.log(`Listening on ${PORT}`);
});
问题:
- 当我向这条路由发送数据时,一切都按预期工作。作业开始,我从服务器收到“作业成功排队”。
- 当我第二次向服务器发送数据时(在前一个作业仍在运行时),路由中的 console.log 不会触发,并且请求会挂起,直到现有作业完成。现有作业完成后,请求得到确认,下一个作业将排队。
我尝试过的事情:
-
使用 spawn() 而不是 spawnSync()。虽然这意味着请求不再被阻止,但这意味着所有作业都同时执行。我研究了 Bull 的并发性,但是当 child_process 像 spawn() 或 exec() 一样异步时,一旦程序成功开始,作业就会被标记为完成 - 它不会等待 spawn() 完成。这意味着服务器认为该作业已完成并愉快地加载到另一个作业中,并且我很快耗尽了内存并且系统崩溃了。 我根本无法限制或控制内存使用量。如果我需要为每个进程提供更多内存,那么我一次只能运行 1 个
-
在 osmQueue.add() 之前简单地调用 res.send()。这对行为没有任何改变。
-
在队列中使用限制器:{max, duration} 选项。如果我将限制持续时间设置为 5 小时,则此方法有效,但这会大大减少我一次可以完成的工作量,降低到无法接受的低水平。
-
我已经阅读并搜索了很长一段时间,但我找不到与我类似的问题。
问题:
- 为什么系统进程在执行 res.send() 后会阻塞 node/express?
- 我应该使用其他库吗?
- 非常感谢知情人士提供的任何见解。
如果还有什么我可以添加的,请告诉我,我会尽快完成。
TL;DR 要求:
将系统进程作为作业的一部分按顺序依次执行,而不会阻止服务器在现有作业运行时将更多作业排队或响应请求。
【问题讨论】:
标签: javascript node.js express bull