SpringBoot应用HTTP连接未关闭,处于CLOSE_WAIT状态求解决方案
解决SpringBoot应用大量连接处于CLOSE_WAIT状态的问题
CLOSE_WAIT状态的核心原因是:对方已经主动关闭了TCP连接,但你的应用没有调用close()方法释放对应的套接字资源,导致连接一直占用系统资源。你配置的server.servlet.session.timeout是控制HTTP会话的超时时间,和TCP连接的生命周期管理无关,所以这个配置无法解决问题。
以下是可行的解决办法:
检查代码中的资源释放逻辑
确保所有涉及网络连接的资源(比如Socket、HttpClient、数据库连接)都被正确关闭:- 优先使用Java的
try-with-resources语法,让资源自动释放,比如Apache HttpClient的使用:try (CloseableHttpClient httpClient = HttpClients.createDefault()) { HttpGet request = new HttpGet("http://example.com"); try (CloseableHttpResponse response = httpClient.execute(request)) { // 处理响应逻辑 } } catch (IOException e) { // 异常处理 } - 检查自定义的TCP服务端/客户端、WebSocket连接,确认在连接断开场景下(比如收到对方关闭信号、业务处理完成)是否调用了
close()方法。
- 优先使用Java的
配置Tomcat的连接超时参数
SpringBoot默认使用Tomcat作为Web容器,通过配置Tomcat的连接参数,可以强制回收闲置连接,避免CLOSE_WAIT堆积:server: tomcat: connection-timeout: 60000 # 连接超时时间,单位毫秒(60秒) max-connections: 8192 # 服务器能处理的最大连接数,根据服务器性能调整 keep-alive-timeout: 30000 # Keep-Alive连接的闲置超时时间 max-keep-alive-requests: 100 # 一个Keep-Alive连接允许处理的最大请求数,超过后关闭连接排查第三方依赖的连接泄漏
很多时候CLOSE_WAIT是第三方依赖的连接泄漏导致的:- 数据库连接池:配置合理的连接生命周期参数,比如HikariCP:
spring: datasource: hikari: max-lifetime: 1800000 # 连接最大生命周期(30分钟),到期自动销毁 idle-timeout: 600000 # 闲置连接超时(10分钟),超时后回收 connection-timeout: 30000 # 获取连接超时时间(30秒) - 使用JVM工具定位问题:通过
jstack命令导出线程栈,查找持有Socket连接但未关闭的线程;用jmap分析堆内存,定位未释放的连接对象。
- 数据库连接池:配置合理的连接生命周期参数,比如HikariCP:
启用操作系统层面的TCP KeepAlive
配置系统的TCP KeepAlive参数,让系统主动检测死连接并回收(以Linux为例):
编辑/etc/sysctl.conf文件,添加以下配置:net.ipv4.tcp_keepalive_time = 600 # 连接闲置10分钟后开始发送探测包 net.ipv4.tcp_keepalive_intvl = 60 # 探测包发送间隔60秒 net.ipv4.tcp_keepalive_probes = 3 # 连续3次探测失败则关闭连接执行
sysctl -p让配置生效。
内容的提问来源于stack exchange,提问作者Abhiram Reddy
相关产品推荐
相关产品推荐

