开发者社区 > 博文 > 一次Druid连接池泄漏的问题排查过程记录
分享
  • 打开微信扫码分享

  • 点击前往QQ分享

  • 点击前往微博分享

  • 点击复制链接

一次Druid连接池泄漏的问题排查过程记录

  • jd_73a242c6ed3bb
  • 2024-07-17
  • IP归属:北京
  • 100浏览

    最近做的一个需求部署测试环境后,运行起来后,发现部分接口出现响应超时情况,一个数据导入接口甚至出现卡顿情况。于是开启了问题排查之路。

    1、定位问题

    接口出现卡顿,首先想到的是看下线程堆栈信息,于是通过jstack命令打印当前线程堆栈。在jdos上提供了便捷的命令操作,如下图所示:

    拿到线程堆栈信息后,根据接口日志上的ThreadId搜索,查看线程的状态。惊奇的发现很多线程都处于WAITING状态,下面提供了堆栈截图:

    从这里就很容易发现了问题,大量的线程都在等待从连接池获取数据库连接。项目中使用了Druid连接池,那是什么造成连接耗尽的呢?慢sql导致线程长时间占有连接?连接池泄漏?连接池配置有问题?

    2、分析问题

      • 慢sql导致的连接长时间未释放?
        • 这个疑问很容易去排查,在易维平台中可以查看慢sql情况。发现没有慢sql存在。解除怀疑。
      • 连接池泄漏?
        • 要分析是否存在连接池泄漏情况,我们需要查看当前连接池中活跃连接情况,还好druid官方提供了监控功能,但是生产一般不建议开启。二话不说,在本地环境开始配置监控功能。参考官网(https://github.com/alibaba/druid)很容易搭建。这里要注意jar包版本,项目中使用的druid版本较低,很多监控不支持。建议升到较高版本操作。由于是在代码发版后出现的问题,就重点看了下新增的代码是否存在连接泄漏情况。一顿操作之后,首先确认了问题是连接池泄漏:打开的连接数>关闭的连接数

    • 确认哪里造成了连接池泄漏,可以点击“活跃连接堆栈查看”,可以看到久久未释放连接的堆栈。如图所示:

    • 按照官网说明配置,连接超时后会被自动释放,并打印日志。进一步确认了问题代码。
    removeAbandoned: true 
    removeAbandonedTimeout: 1800
    logAbandoned: true
    
    • 连接被动释放时的日志截取:
    [ERROR] (Druid-ConnectionPool-Destroy-228035257) [com.alibaba.druid.pool.DruidDataSource:2915]: abandon connection, owner thread: http-nio-80-exec-2, connected at : 1663564101647, open stackTrace
    	at java.lang.Thread.getStackTrace(Thread.java:1564)
    	at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:1460)
    	at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:5059)
    	at com.alibaba.druid.filter.FilterAdapter.dataSource_getConnection(FilterAdapter.java:2756)
    	at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:5055)
    	at com.alibaba.druid.filter.stat.StatFilter.dataSource_getConnection(StatFilter.java:680)
    	at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:5055)
    	at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1373)
      at com.alibaba.druid.pool.DruidDataSource.getConnection(DruidDataSource.java:1365)
    
    • 这里犯了一个低级错误,在使用sqlSession操作之后,没有关闭。造成了连接池泄漏。

    3、总结

    在进行druid监控配置过程中,发现代码中的druid属性配置并未生效。由一个泄漏问题排查出另外一个项目配置的问题。druid的配置,官网提供了两种方式。一种是通过https://github.com/alibaba/druid/tree/master/druid-spring-boot-starter/,一种是通过spring集成。但是要特别注意,通过spring集成时,yml文件中配置的druid属性,需要我们手动加载。可参考(https://segmentfault.com/a/1190000039005979

    @ConfigurationProperties(prefix = "spring.datasource")
    @Bean
    public DataSource dataSource() {
        return new DruidDataSource();
    }
    


    文章数
    1
    阅读量
    0

    作者其他文章