Node/HAPI:并发连接过多导致网络连接重置问题排查求助
这种连接重置的问题我在高并发的Node.js服务场景下碰过好几次,结合你已经确认异步操作都做了的情况,咱们从系统、框架、Node本身这几个层面一步步排查:
1. 先排查系统层面的文件描述符限制
每个TCP连接对应一个文件描述符,系统默认的限制往往很低(比如1024),并发上来很容易耗尽:
- 用
ulimit -n查看当前Node进程的软限制,ulimit -Hn查看硬限制。如果数值低于万级,那基本就是瓶颈了。 - 统计Node进程实际打开的文件描述符数量:
lsof -p <你的Node进程ID> | wc -l,如果这个数接近ulimit的限制,实锤是这个问题。 - 临时调整可以用
ulimit -n 65535(只对当前会话有效),永久生效需要修改/etc/security/limits.conf,添加:
之后重启Node进程。* soft nofile 65535 * hard nofile 65535
2. 检查HAPI的连接与超时配置
HAPI底层依赖Node的HTTP模块,一些默认配置可能导致连接无法及时释放:
- 调整服务器的超时参数,避免空闲连接长期占用Socket:
const server = Hapi.server({ port: 3000, routes: { timeout: { server: 30000, // 服务器处理超时,超时后主动关闭连接 socket: 30000 // Socket空闲超时 } }, listener: { keepAliveTimeout: 5000, // 保持连接超时,空闲超过5秒就关闭 headersTimeout: 60000 // 请求头接收超时,避免恶意连接挂着 } }); - 确保全局错误处理覆盖所有异常,避免未捕获的错误导致连接被强制重置:
server.ext('onPreResponse', (request, h) => { const res = request.response; if (res.isBoom) { // 记录错误日志,确保响应正常返回给客户端 console.error(`[${request.path}] Error:`, res.message); return h.response({ error: res.message }).code(res.output.statusCode); } return h.continue; });
3. 排查Node.js的Socket管理
Node的HTTP模块有一些全局参数可能影响连接:
- 默认的
http.Agent(服务器端处理连接时也会用到)有maxFreeSockets(默认256),如果空闲Socket没及时回收,也会占用资源。可以尝试调整这个值:const http = require('http'); http.globalAgent.maxFreeSockets = 1024; - 用Node内置的工具排查活跃连接:在代码里定时打印
process._getActiveHandles().filter(h => h instanceof net.Socket).length,看是否有持续增长的Socket数量。 - 用性能分析工具(比如
clinic bubbleprof)生成火焰图,直观查看是否有未释放的连接或阻塞点。
4. 抓包确认重置细节
用tcpdump抓包看连接重置的发起方和时机:
- 执行
sudo tcpdump -i any port <你的服务端口> -w connection_reset.pcap,然后复现问题,用Wireshark打开分析。 - 如果是服务器主动发送RST包,说明服务器端资源耗尽或主动关闭;如果是客户端发起,可能是客户端超时,但结合并发增长的场景,大概率是服务器端的问题。
总结解决步骤
- 先把系统文件描述符限制调到65535左右,这是最常见的高并发瓶颈。
- 配置HAPI的超时参数,确保空闲连接及时释放。
- 完善全局错误处理,避免异常导致连接异常关闭。
- 用工具排查是否有未释放的Socket或请求。
内容的提问来源于stack exchange,提问作者Jem
相关产品推荐
相关产品推荐

