高并发SqlSession close前新开SqlSession导致阻塞问题

最近测试程序的高并发,发现高并发下卡死,百分之百复现。经过一天的调查,最终定位问题所在。

程序结构为:

SqlSession session = DbUtil.getSession();
try{
...

    SqlSession session2 = DbUtil.getSession();
    try{

    ...
    
    } finally {
        session2.close();
    }

...

} finally {
    session.close();
}

当高并发访问时,session申请掉了所有的数据库连接,当进入到session2时,无法获取到新的数据库连接,阻塞,导致session无法执行到close,没有新的连接可用,整个程序无法获取新的数据库连接。

可以尝试减少服务的最大线程数,增加数据库的最大连接数,使得数据库连接数大于服务线程数。但是这样治标不治本。

能想到两个办法:

1、将这种session内申请session的都修改要么移到session外,要么使用前面的session。也就是从代码逻辑上规避。

2、设置Druid的MaxWait,例如设置为2000(毫秒)

参考:

Druid数据库连接池配置(案例及排查指南)

https://tech.youzan.com/shu-ju-ku-lian-jie-chi-pei-zhi/

更新:

设置Druid的removeAbandoned,removeAbandonedTimeout将超过20秒的连接停止掉。

设置logAbandoned打印出来abandoned的连接。

https://www.cnblogs.com/spec-dog/p/6226212.html

总结:

1、修改代码,将所有事务内嵌套事务改为单线事务
2、优化代码,对于查数据库能缓存的做缓存处理;优化sql
3、尝试不同的Druid连接池配置及ICE最大线程数,寻找较优组合
4、配置Druid的removeAbandoned,释放长时间未完成的连接
5、更新Druid、pg库
6、尝试将Druid更换为HiKariCP,未见改善,改回Druid

发表评论

电子邮件地址不会被公开。 必填项已用*标注