【发布时间】:2021-10-12 19:24:23
【问题描述】:
我正在探索如何中止耗时过长的客户端请求,从而消耗服务器资源。 阅读了一些资料(见下文)后,我尝试了如下解决方案(建议here):
const express = require('express');
const server = express();
server
.use((req, res, next) => {
req.setTimeout(5000, () => {
console.log('req timeout!');
res.status(400).send('Request timeout');
});
res.setTimeout(5000, () => {
console.log('res timeout!');
res.status(400).send('Request timeout');
});
next();
})
.use(...) // more stuff here, of course
.listen(3000);
但是,它似乎不起作用:回调永远不会被调用,请求也不会被中断。 然而,根据recent posts,它应该。
除了全局设置超时(即server.setTimeout(...)),这不适合我的用例,
我看到很多人建议使用connect-timeout 中间件。
但是,我在其文档中读到
While the library will emit a ‘timeout’ event when requests exceed the given timeout, node will continue processing the slow request until it terminates.
Slow requests will continue to use CPU and memory, even if you are returning a HTTP response in the timeout callback.
For better control over CPU/memory, you may need to find the events that are taking a long time (3rd party HTTP requests, disk I/O, database calls)
and find a way to cancel them, and/or close the attached sockets.
我不清楚如何“找到需要很长时间的事件”和“取消它们的方法”, 所以我想知道是否有人可以分享他们的建议。 这甚至是正确的方法,还是有更现代的“标准”方法?
规格:
- 节点 12.22
- Ubuntu 18.04
- Linux 5.4.0-87-generic
来源:
- Express.js Response Timeout
- Express.js connect timeout vs. server timeout
- Express issue 3330 on GitHub
- Express issue 4664 on GitHub
编辑: 我已经看到一些答案和 cmets 提供了一种在 responses 或“请求处理程序”上设置超时的方法:换句话说,中间件花费的时间被测量,如果花费太长时间则中止。但是,我正在寻找一种使 requests 超时的方法,例如在客户端通过慢速连接发送大文件的情况下。这可能甚至在快速路由器中的第一个处理程序之前发生,这就是为什么我怀疑服务器级别必须有某种设置。
【问题讨论】:
-
这取决于究竟是什么需要很长时间。如果你阻塞了主线程,那么你就没有什么可做的了。但是如果它的一些异步调用包装在一个承诺中,你可以把它包装在 bluebir 的超时承诺中:bluebirdjs.com/docs/api/timeout.html
-
如果您无法控制那个耗时的任务,我认为唯一正确的方法是
process.exit,它将终止整个实例和所有子进程(异步)。它会引导你到cluster,当他们中的任何一个因任何原因死亡时,它会负责重生新工人。
标签: javascript node.js express