close_wait过多服务器无响应,记一次大量CLOSE_WAIT连接导致的服务宕机

最近线上服务出现了一段时间的无法响应,在此总结一下问题的排查过程。

监控信息

bVbcjiO?w=533&h=298

监控显示CPU和内存没有异常波动,TCP连接中有大量的CLOSE_WAIT状态的连接。

看一下TCP连接断开的过程:

bVbcjkv?w=640&h=496

也就是说客户端发起了断开连接的包,服务端收到数据后状态变更为CLOSE_WAIT,这时需要等待服务端处理完连接中未发送完的数据之后发送FIN给客户端,但是服务端此时可能因为各种原因,中断在了这个环节,导致操作系统的连接数被CLOSE_WAIT占用,没有足够资源响应客户端请求。所以接下来就需要查清楚服务端到底在忙什么,为什么不继续完成断开连接的四次挥手过程。

线程栈

对于Java应用,可以利用JDK提供的工具查看线程的栈。

jstack -l pid

其中pid是JVM进程的ID

bVbcjoz?w=1026&h=223

打印出的栈信息中可以发现大量类似上图的WAITING状态的线程,线程在以下几种情况会进入WAITING状态:

Object的wait方法,并且没有使用timeout参数;

Thread的join方法,没有使用timeout参数;

LockSupport的park方法。

如果一个线程调用了一个对象的wait方法,那么这个线程就会处于waiting状态直到另外一个线程调用这个对象的notify或者notifyAll方法后才会解除这个状态。

bVbcjqH?w=652&h=614

具体到此处的问题,可以理解为数据库连接池中获取连接时,没有可用连接,此时调用notEmpty.await();等待有连接释放回收到连接池或创建新的连接后notify当前线程再来获取连接。所以此时问题的根本原因是数据库连接池耗尽,一直在wait可用连接,线程无法继续执行下去。

数据库连接池的配置

我的应用是基于springboot开发的,在技术社区也查到了一些关于springboot的默认数据库连接配置可能会存在潜在风险。数据连接池默认配置带来的坑

简单来说,默认的数据连接配置,可能会导致连接池中的连接是不可用的,但是仍在连接池中充数,并不会被释放。增加了以下几个参数,DONE!

testWhileIdle: true

validationQuery: SELECT 1

timeBetweenEvictionRunsMillis: 60000

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值