已配置Nginx keepalive_timeout=1h,为何与Node.js的Socket仍断开?
关于Nginx与Node.js之间Keep-Alive连接提前断开的疑问
为理解Keep-Alive机制,我编写了一个Node.js小型HTTP服务器,源码如下:
const http = require('http'), server = http.createServer((req, res) => { const socket = req.socket, socketId = socket._handle.fd; console.info(`Writing response to the socket ${socketId}`); res.writeHead(200, { 'Content-Type': 'application/json' }); res.end('okay'); }); server.on('clientError', (err) => { if (err) { console.error(err); } }); function getSocketCloseFn (socketId) { return function onSocketClose (hadError) { if (hadError) { console.error(`Found error in the socket ${socketId}`); } console.info(`Socket ${socketId} is closed`); }; } server.on('connection', (socket) => { console.info('A new TCP connection is created on port', socket.localPort, socket._handle.fd); socket.on('close', getSocketCloseFn(socket._handle.fd)); }); server.listen(7690, () => { console.info('server listening at port 7690'); });
同时使用Nginx作为反向代理,配置如下:
upstream backend { server 127.0.0.1:7690; keepalive 8; keepalive_timeout 3600; } server { listen 9678; location / { proxy_pass http://backend; proxy_set_header Host $host; proxy_http_version 1.1; proxy_set_header Connection ""; } }
服务器日志如下:
A new TCP connection is created on port 7690 19 A new TCP connection is created on port 7690 20 Writing response to the socket 19 Writing response to the socket 20 Writing response to the socket 20 Writing response to the socket 20 Writing response to the socket 20 Writing response to the socket 20 Writing response to the socket 20 Writing response to the socket 20 Socket 19 is closed Socket 20 is closed A new TCP connection is created on port 7690 19 A new TCP connection is created on port 7690 20 Writing response to the socket 19 Writing response to the socket 20 Socket 20 is closed Socket 19 is closed A new TCP connection is created on port 7690 19 Writing response to the socket 19 Writing response to the socket 19 Writing response to the socket 19 Writing response to the socket 19 A new TCP connection is created on port 7690 20 Writing response to the socket 20 Writing response to the socket 20 Writing response to the socket 20 A new TCP connection is created on port 7690 21 Writing response to the socket 21 Socket 19 is closed Socket 21 is closed Socket 20 is closed
核心疑问:即使在Nginx配置中设置了keepalive_timeout 3600;,为何Nginx与Node.js服务器之间的Socket连接仍会断开?TCP连接难道不应保持1小时吗?
问题原因分析与解决
1. Node.js HTTP服务器的默认Keep-Alive超时
Node.js的http模块默认配置了空闲连接超时时间,当前多数版本中这个默认值是5秒(旧版可能为2分钟)。也就是说,当TCP连接空闲超过这个时间,Node.js服务器会主动关闭连接,这个行为不受Nginx的keepalive_timeout影响——因为后端主动关闭连接后,Nginx只能随之断开。你的代码里没有修改这个默认值,所以连接会被提前关闭。
2. Nginx的Keep-Alive配置逻辑
Nginx的keepalive_timeout是指Nginx自身保持空闲连接的时长,但它无法阻止后端服务主动关闭连接。另外,keepalive 8是设置Nginx维护的空闲连接池最大数量,从你的日志看,连接数远未达到这个上限,所以不是这个因素导致的断开。
3. 解决方法
要让连接保持1小时,需要同步Node.js和Nginx的超时配置,在Node.js服务器中添加以下代码:
server.listen(7690, () => { console.info('server listening at port 7690'); // 设置Keep-Alive空闲超时为1小时 server.keepAliveTimeout = 3600 * 1000; // headersTimeout需略大于keepAliveTimeout,避免因响应头未及时处理提前关闭 server.headersTimeout = 3600 * 1000 + 1000; });
修改后,Node.js服务器会将空闲连接的超时时间调整为1小时,和Nginx的配置匹配,连接就不会被提前断开。
内容的提问来源于stack exchange,提问作者Onbit
相关产品推荐
相关产品推荐

