阿里Druid數(shù)據(jù)連接池引發(fā)的線(xiàn)上異常解決

前言
事件起因:項(xiàng)目使用了activiti工作流,系統(tǒng)是由老的spring mvc項(xiàng)目改造成的spring boot項(xiàng)目,數(shù)據(jù)庫(kù)鏈接池從dbcp切換到druid,新系統(tǒng)上線(xiàn)后,同事多次系統(tǒng)隔一段時(shí)間后數(shù)據(jù)查詢(xún)就很慢,基本出不來(lái)。
由此開(kāi)始了線(xiàn)上bug排查之路。這個(gè)問(wèn)題從一開(kāi)始就模糊定位到數(shù)據(jù)庫(kù)層面的問(wèn)題,因?yàn)橹挥泻蛿?shù)據(jù)相關(guān)的操作會(huì)很慢,其他服務(wù)不受影響,并且在中午休息時(shí)沒(méi)有問(wèn)題,在下午剛上班后不就出現(xiàn)。
過(guò)程一:定位工作流
首先第一反應(yīng)是看日志:日志一切正常,并沒(méi)有任何異常信息拋出,然后將日志級(jí)別調(diào)整到debug,發(fā)現(xiàn)了一些問(wèn)題,中午休息時(shí),用戶(hù)沒(méi)有操作的情況下,日志一直在輸出jpa的連接信息,最后定位是工作流的異步執(zhí)行器在輪詢(xún),因?yàn)樵趕pring boot環(huán)境下spring.activiti.async-executor-activate=true默認(rèn)是true的,如果不需要使用可以設(shè)置為false,改完后情況依舊
過(guò)程二:定位JPA的OpenEntityManagerInViewInterceptor
使用OpenEntityManagerInViewInterceptor后服務(wù)端在接收到一個(gè)請(qǐng)求的時(shí)候開(kāi)啟EntityManager,在請(qǐng)求結(jié)束的時(shí)候才去關(guān)閉這個(gè)EntityManager,所以在用戶(hù)數(shù)多,并發(fā)高,操作耗時(shí)的情況下會(huì)造成數(shù)據(jù)連接不夠用的情況,而我們的業(yè)務(wù)有這個(gè)特征。
在spring boot環(huán)境中,OpenEntityManagerInViewInterceptor默認(rèn)是開(kāi)啟的,然而我們使用spring.jpa.open-in-view=false關(guān)閉后,問(wèn)題依舊,不過(guò)比之前的間隔時(shí)間久一點(diǎn)了
過(guò)程三:定位Druid,真正的罪魁禍?zhǔn)?/h2>
使用top定位到程序pid,然后使用jstack -l 2591 >>dump.out 拿到當(dāng)前堆??煺蘸蟀l(fā)現(xiàn)如下
"http-nio-8080-exec-54" daemon prio=10 tid=0x0000000000e61000 nid=0xcc9 waiting on condition [0x00007f4a753d4000] java.lang.Thread.State: WAITING (parking) at sun.misc.Unsafe.park(Native Method) - parking to wait for <0x00000007a143f230> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject) at java.util.concurrent.locks.LockSupport.park(LockSupport.java:186) at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2043) at com.alibaba.druid.pool.DruidDataSource.takeLast(DruidDataSource.java:1732) at com.alibaba.druid.pool.DruidDataSource.getConnectionInternal(DruidDataSource.java:1330) at com.alibaba.druid.pool.DruidDataSource.getConnectionDirect(DruidDataSource.java:1198) at com.alibaba.druid.filter.FilterChainImpl.dataSource_connect(FilterChainImpl.java:4619)
所有的請(qǐng)求都被druid的獲取連接操作阻塞了,最后看源碼如下

因?yàn)閿?shù)據(jù)鏈接沒(méi)有釋放,連接池中無(wú)可用連接,導(dǎo)致請(qǐng)求被阻塞了
到這里基本上就是真相了,最后換成spring boot自帶的連接池tomcat jdbc后一切正常
后記:
定位到問(wèn)題后,發(fā)現(xiàn)網(wǎng)上很多人遇到了連接泄露的情況,可見(jiàn)druid的官方issue,如https://github.com/alibaba/druid/issues/1160
不過(guò)druid也提供了相應(yīng)的方案,如下

雖然官方說(shuō)可能是應(yīng)用自己導(dǎo)致連接未被釋放導(dǎo)致連接泄露,但是為什么切換別家的連接池后就毛事都沒(méi)有呢,元芳,你怎么看呢?
以上就是阿里Druid數(shù)據(jù)連接池引發(fā)的線(xiàn)上異常解決的詳細(xì)內(nèi)容,更多關(guān)于Druid數(shù)據(jù)連接池線(xiàn)上異常的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
java中ArrayList與LinkedList對(duì)比詳情
這篇文章主要通過(guò)實(shí)例對(duì)Java中ArrayList與LinkedList進(jìn)行了對(duì)比,需要的朋友可以參考下2017-04-04
mybatis-plus如何修改日志只打印SQL語(yǔ)句不打印查詢(xún)結(jié)果
這篇文章主要介紹了mybatis-plus如何修改日志只打印SQL語(yǔ)句不打印查詢(xún)結(jié)果問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06
Apache Commons fileUpload實(shí)現(xiàn)文件上傳之一
這篇文章主要介紹了Apache Commons fileUpload實(shí)現(xiàn)文件上傳之一的相關(guān)資料,需要的朋友可以參考下2016-03-03
SpringBoot如何使用@Aspect注解實(shí)現(xiàn)AOP
這篇文章主要介紹了SpringBoot如何使用@Aspect注解實(shí)現(xiàn)AOP問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07
Java8實(shí)現(xiàn)對(duì)List<Integer>的求和
這篇文章主要介紹了Java8實(shí)現(xiàn)對(duì)List<Integer>的求和方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-05-05

