Node.js 为什么NodeJS http服务器在超时时关闭套接字而没有响应?
给定超时为10秒的NodeJS http服务器:Node.js 为什么NodeJS http服务器在超时时关闭套接字而没有响应?,node.js,express,httpserver,nginx-reverse-proxy,Node.js,Express,Httpserver,Nginx Reverse Proxy,给定超时为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 s
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将返回502响应(从上游读取响应头时,上游连接过早关闭)。但这里它只是在localhost上运行的NodeJS/express。人们仍然希望得到正确的http响应
根据,这是预期的行为,套接字被简单地销毁
在使用nginx反向代理的体系结构中,服务器通常只销毁套接字而不向代理发送超时响应吗?您正在设置。套接字超时可防止可能希望挂起您的连接以拒绝您的客户端滥用。它还有其他好处,比如确保一定水平的服务(尽管当你是客户时,这些好处往往更为重要)
它使用套接字超时而不是发送408
状态代码(请求超时)的原因是,可能已经为成功的消息发送了状态代码
如果您想在后端实现响应超时并优雅地处理它,您可以自己超时响应。注意,您可能应该使用408
来响应502
用于http代理(nginx)等网关,用于指示下游连接失败
下面是一个简单的strawman实现
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);
你在设定目标。套接字超时可防止可能希望挂起您的连接以拒绝您的客户端滥用。它还有其他好处,比如确保一定水平的服务(尽管当你是客户时,这些好处往往更为重要)
它使用套接字超时而不是发送408
状态代码(请求超时)的原因是,可能已经为成功的消息发送了状态代码
如果您想在后端实现响应超时并优雅地处理它,您可以自己超时响应。注意,您可能应该使用408
来响应502
用于http代理(nginx)等网关,用于指示下游连接失败
下面是一个简单的strawman实现
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);
谢谢,请您详细说明“状态码可能已经发送成功的消息。”?根据我的理解,如果已经发送了响应,套接字就不会超时。客户端可能会发出请求,然后再也不会尝试读取响应,从而保持连接。响应首先发送状态代码。(请参阅这些以获得良好的概述)。因此,您无法关闭插座并更改已通过导线发送的状态。在HTTP1.x中,先是状态,然后是标题,然后是正文。维基百科上有一篇关于不同DDOS攻击的好文章。其中一个是,在其他类似的攻击中,通过超时底层套接字在一定程度上减轻了攻击,但无法在HTTP层本身进行防御。如果我没有弄错的话,setTimeout
的回调仅在请求超时时调用,而不是在keepalive超时时调用。在这两种情况下套接字都会被破坏,但只有在第一种情况下才会发送代码示例中的408
。因此,这与Slowloris攻击无关,并且不可能已经发送响应,或者我错了吗?正确,setTimeout只是用于超时请求,但它本身并不处理套接字超时。如果需要,您可以通过抓取请求的套接字并为on:timeout
事件添加自己的处理程序来处理该问题,但是您仍然应该确保关闭套接字。您是对的,如果套接字超时小于这两个值中的任何一个,您将得到相同的旧套接字超时,因此套接字超时应该大于您的请求超时。套接字超时只有在出现不稳定的情况下才会发生。谢谢,请您详细说明“状态码可能已经发送了一条成功的消息。”?根据我的理解,如果已经发送了响应,套接字就不会超时。客户端可能会发出请求,然后再也不会尝试读取响应,从而保持连接。响应首先发送状态代码。(请参阅这些以获得良好的概述)。因此,您无法关闭插座并更改已通过导线发送的状态。在HTTP1.x中,先是状态,然后是标题,然后是正文。维基百科上有一篇关于不同DDOS攻击的好文章。其中一个是,在其他类似的攻击中,通过超时底层套接字在一定程度上减轻了攻击,但无法在HTTP层本身进行防御。如果我没有弄错的话,setTimeout
的回调仅在请求超时时调用,而不是在keepalive超时时调用。在这两种情况下套接字都会被破坏,但只有在第一种情况下才会发送代码示例中的408
。因此,这与Slowloris攻击无关,并且不可能已经发送响应,或者我错了吗?正确,setTimeout只是用于超时请求,但它本身并不处理套接字超时。如果需要,您可以通过抓取请求的套接字并为on:timeout
事件添加自己的处理程序来处理该问题,但是您仍然应该确保关闭套接字。您是对的,如果套接字超时小于这两个值中的任何一个,您将得到相同的旧套接字超时,因此套接字超时应该大于您的请求超时。套接字超时只有在发生不稳定的事情时才会发生。