????自從項(xiàng)目從PSSql數(shù)據(jù)庫(kù)切換到mysql后,時(shí)長(zhǎng)會(huì)出現(xiàn) SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@21db37de] was not registered for synchronization because synchronization is not active。所有頁面卡頓,服務(wù)基本就掛了,本以為是偶爾事件,結(jié)果暴力重啟后,一段時(shí)間再次出現(xiàn)了。頁面出現(xiàn)卡頓,一開始就覺得應(yīng)該是線程死鎖,jvm內(nèi)存撐滿,導(dǎo)致GC頻繁。
所以,首先檢查jvm。。。
查看cpu情況,top -Hp pid

如圖所示,cpu最大才占用2%,內(nèi)存最大也才5%,所以明顯不是線程死鎖導(dǎo)致的。
繼續(xù)排查。。。
查看gc情況,jstat -gc pid


如圖,即便Eden區(qū)和from區(qū)數(shù)據(jù)滿了,但總體的GC情況還是可控的,所以也不是這里的問題。
導(dǎo)出dump文件, jmap -dump:format=b,file=heap.hprof 20210,使用jprofiler查看當(dāng)前創(chuàng)建對(duì)象數(shù)。

如圖,當(dāng)前存在的對(duì)象,最多的也只有13kb,所以不太可能是內(nèi)存問題,但很明顯jvm內(nèi)存需要增加了。。。
至此,確認(rèn)不是jvm問題,開始排除mysql數(shù)據(jù)庫(kù)問題。仔細(xì)分析接口請(qǐng)求,發(fā)現(xiàn)
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@30579c64] was not registered for synchronization because synchronization is not active
JDBC Connection [com.mysql.cj.jdbc.ConnectionImpl@5ad7e3ac] will not be managed by Spring
懷疑是不是請(qǐng)求連接數(shù)據(jù)庫(kù),但連接沒有被釋放。查看durid連接池的配置。

所有參數(shù)都是默認(rèn)的。上網(wǎng)查找druid參數(shù)詳解,參考連接 https://blog.csdn.net/weixin_33924770/article/details/94117616
數(shù)據(jù)庫(kù)連接池在初始化的時(shí)候會(huì)創(chuàng)建initialSize個(gè)連接,當(dāng)有數(shù)據(jù)庫(kù)操作時(shí),會(huì)從池中取出一個(gè)連接; 如果當(dāng)前池中正在使用的連接數(shù)等于maxActive,則會(huì)等待一段時(shí)間,等待其他操作釋放掉某一個(gè)連接,如果這個(gè)等待時(shí)間超過了maxWait,則會(huì)報(bào)錯(cuò)。默認(rèn)值并沒有設(shè)置maxWait,所以估計(jì)它會(huì)一直等待下去,導(dǎo)致頁面卡頓,一直刷不出來。
連接池配置文件中添加參數(shù):
initialSize: 20
min-idle: 20
max-active: 100
max-wait: 3000
time-between-eviction-runs-millis: 60000
至此的確不在出現(xiàn)頁面卡頓這個(gè)問題了。
?但新的問題來了,只要服務(wù)運(yùn)行一段時(shí)間,又會(huì)出現(xiàn)報(bào)錯(cuò)。。。。

這種報(bào)錯(cuò),表明數(shù)據(jù)庫(kù)連接太多,已經(jīng)將連接池中的連接撐滿,導(dǎo)致有再次請(qǐng)求是等待超時(shí),報(bào)錯(cuò)。。。。
這就奇怪了,難道是druid,沒有管理連接池嗎??難道請(qǐng)求一次,就會(huì)新建一個(gè)新的連接???
查看數(shù)據(jù)庫(kù)
數(shù)據(jù)庫(kù)最大連接數(shù)
show variables like ‘%max_connections%’;
當(dāng)前連接數(shù)
show full processlist;
果然發(fā)現(xiàn)每請(qǐng)求一次,就會(huì)增加一條連接數(shù)。。。
排查代碼。。。
最后發(fā)現(xiàn)有人在代碼里手寫開啟數(shù)據(jù)庫(kù)連接,然后沒有關(guān)閉,也沒有拋出異常。結(jié)果我們沒有捕獲到異常,在完全不知情的情況下,花了幾天時(shí)間排查問題。。。。。。。。。
????這里做一個(gè)問題排查總結(jié),這一次雖然是代碼上的問題,但從問題出現(xiàn),與原因分析,對(duì)于一個(gè)完全沒有jvm故障排查經(jīng)驗(yàn)的人來說,是一份很好的經(jīng)歷,雖然過程曲折,到從jvm,數(shù)據(jù)庫(kù),到druid連接池配置,都是一次難得的回憶。。。。。
ps:我們也曾經(jīng)調(diào)試過druid配置:removeAbandoned?如果連接泄露,是否需要回收泄露的連接,但也不是這個(gè)原因,所以的原因都分析過了,再重新看代碼時(shí)就會(huì)充滿懷疑。。