首页 > 解决方案 > 为什么NodeJS http服务器在超时时关闭套接字而没有响应?

问题描述

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

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

超时时,邮递员会在没有任何响应代码的情况下显示此内容:

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

如果 NodeJS 服务器位于 nginx 反向代理之后,则 nginx 返回 502 响应 ( upstream prematurely closed connection while reading response header from upstream)。但这里只是在 localhost 上运行的 NodeJS/express。仍然有人会期望适当的 http 响应。

根据这个答案,这是预期的行为,套接字被简单地破坏了。

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

标签: node.jsexpresshttpservernginx-reverse-proxy

解决方案


当您设置 http server timeout 时,您正在设置套接字超时。套接字超时可防止可能希望挂在您与 DOS 之间的连接的客户端滥用。它还有其他好处,例如确保一定水平的服务(尽管当您是客户时这些通常更重要)。

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

如果您想在后端实现响应超时并优雅地处理它,您可以自己超时响应。请注意,您可能应该用 a408代替。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);

推荐阅读