Node.js发起HTTP请求后连接卡在CLOSE_WAIT状态的问题求教
问题根因分析
CLOSE_WAIT状态的本质是对端(你的家用路由器)已经主动发送了FIN包请求关闭连接,但是本地Node.js进程没有主动释放对应的TCP套接字资源,导致连接一直卡在该状态。
和Nginx、Portainer没有出现该问题的原因是:家用路由器用的是裁剪过的嵌入式HTTP服务,对HTTP长连接的处理逻辑不规范,不会主动回收空闲长连接;而标准HTTP服务器会主动断开超时的空闲长连接,不会让连接一直挂起。
代码优化方案
- 新增
Connection: close请求头,明确告知路由器本次请求不需要保持长连接,请求完成后直接断开,规避路由器对长连接的处理缺陷 - 给请求添加超时机制,超时后主动销毁套接字,避免无限等待
- 响应流接收完成后主动销毁请求和响应对象,删除冗余的close事件end调用逻辑
- 确保所有异常分支都正确销毁套接字资源
修改后的代码如下:
function httpCheck(name, host, port, path) { const httpRequest = http.get( `http://${host}:${port}${path}`, { headers: { 'Connection': 'close' } }, // 核心修改:禁用长连接 (response) => { if (debug) console.log(`HTTP check for http://${host}:${port}${path} returned: ${response.statusCode}`); if (response.statusCode < 400) publishStatus(name, config.statusMsg.success); else publishStatus(name, config.statusMsg.failure); // 消费完响应后主动销毁资源 response.on('end', () => { response.destroy(); httpRequest.destroy(); }); // 响应出错也销毁资源 response.on('error', (err) => { response.destroy(); httpRequest.destroy(); }); } ); // 5秒超时,可根据实际网络情况调整 httpRequest.setTimeout(5000, () => { publishStatus(name, config.statusMsg.failure); httpRequest.destroy(); }); // 消费响应数据,避免响应流卡住 httpRequest.on('data', () => {}); // 请求出错时销毁资源 httpRequest.on('error', (err) => { publishStatus(name, config.statusMsg.failure); httpRequest.destroy(); }); }
内容的提问来源于stack exchange,提问作者Dave H.
相关产品推荐
相关产品推荐

