为什么 NodeJS http 服务器在超时时关闭套接字而没有响应?

Why does a NodeJS http server close socket on timeout without response?

给定一个超时为 10 秒的 NodeJS http 服务器:

const httpServer = require('http').createServer(app);
httpServer.timeout = 10 * 1000;

超时时,Postman 显示没有任何响应代码:

Error: socket hang up
Warning: This request did not get sent completely and might not have all the required system headers

如果 NodeJS 服务器在 nginx 反向代理之后,nginx returns 502 响应 (upstream prematurely closed connection while reading response header from upstream)。但这里它只是本地主机上的 NodeJS/express 运行。仍然有人会期待正确的 http 响应。

根据this answer,这是预期的行为,套接字被简单地销毁了。

在具有 nginx 反向代理的架构中,服务器通常只是销毁套接字而不向代理发送超时响应吗?

您正在设置 socket timeout when you're setting the http server timeout。套接字超时可防止可能想要挂在您与 DOS 的连接上的客户端滥用。它还有其他好处,例如确保一定程度的服务(尽管当您是客户时这些通常更为重要)。

它使用套接字超时而不是发送 408 状态代码(请求超时)的原因是因为成功消息可能已经发送了状态代码。

如果您想在后端实现响应超时并优雅地处理它,您可以自己设置响应超时。请注意,您可能应该使用 408 来响应。 502 用于 http 代理 (nginx) 等网关,指示下游连接失败。

这是处理该问题的简单稻草人实现。

const httpServer = require('http').createServer((req, res) => {
    setTimeout(()=>{
        res.statusCode = 200;
        res.statusMessage = "Ok";
        res.end("Done"); // I'm never called because the timeout will be called instead;
    }, 10000)
});

httpServer.on('request', (req, res) => {
    setTimeout(()=>{
        res.statusCode = 408;
        res.statusMessage = 'Request Timeout';
        res.end();
    }, 1000)
});

httpServer.listen(8080);