本篇內(nèi)容主要講解“如何解決dbcp連接池連接失效問題”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“如何解決dbcp連接池連接失效問題”吧!
創(chuàng)新互聯(lián)專注于企業(yè)成都營銷網(wǎng)站建設(shè)、網(wǎng)站重做改版、九原網(wǎng)站定制設(shè)計(jì)、自適應(yīng)品牌網(wǎng)站建設(shè)、H5高端網(wǎng)站建設(shè)、商城建設(shè)、集團(tuán)公司官網(wǎng)建設(shè)、外貿(mào)網(wǎng)站建設(shè)、高端網(wǎng)站制作、響應(yīng)式網(wǎng)頁設(shè)計(jì)等建站業(yè)務(wù),價(jià)格優(yōu)惠性價(jià)比高,為九原等各大城市提供網(wǎng)站開發(fā)制作服務(wù)。
a.log的錯(cuò)誤日志報(bào)了MySQL的連接問題,時(shí)間在16:35分左右
[2016-09-14 16:35:03.643]Last packet sent to the server was 8 ms ago.; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException: [2016-09-14 16:35:03.643]--- The error occurred in sqlmaps/friend/FriendsInviteSQL.xml. [2016-09-14 16:35:03.643]--- The error occurred while applying a parameter map. [2016-09-14 16:35:03.643]--- Check the FriendsInvite.getLastInvited-InlineParameterMap. [2016-09-14 16:35:03.643]--- Check the statement (query failed). [2016-09-14 16:35:03.643]--- Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure [2016-09-14 16:35:03.643] [2016-09-14 16:35:03.643]Last packet sent to the server was 8 ms ago. [2016-09-14 16:35:03.643] at com.xx.core.dao.msroute.MasterSlaveDatasourceInteceptor.invoke(MasterSlaveDatasourceInteceptor.java:61) ~[MasterSlaveDatasourceInteceptor.class:na] [2016-09-14 16:35:03.643] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) ~[ReflectiveMethodInvocation.class:3.1.2.RELEASE] [2016-09-14 16:35:03.643] at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) ~[JdkDynamicAopProxy.class:3.1.2.RELEASE] [2016-09-14 16:35:03.643] at com.sun.proxy.$Proxy101.getLastInvited(Unknown Source) ~[na:na] [2016-09-14 16:35:03.643] at com.xx.user.friend.manager.FriendsManager.getLastInviter(FriendsManager.java:160) ~[classes:na] [2016-09-14 16:35:03.643] at com.xx.user.friend.manager.FriendsManager$$FastClassByCGLIB$$1076743a.invoke( |
隨后不斷有同樣的異常報(bào)出,且時(shí)間間隔在不斷加大,到19:35的時(shí)候已經(jīng)是12175秒了。
[2016-09-14 19:35:52.934]--- Cause: com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: The last packet successfully received from the server was12175 seconds ago.The last packet sent successfully to the server was 12175 seconds ago, which is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.; nested exception is com.ibatis.common.jdbc.exception.NestedSQLException: |
起初是認(rèn)為只有a數(shù)據(jù)庫有問題,后來發(fā)現(xiàn)b數(shù)據(jù)庫也報(bào)這個(gè)問題。判斷應(yīng)該是連接池中的連接已經(jīng)失效的問題。
mysql數(shù)據(jù)庫dba那邊的超時(shí)時(shí)間設(shè)置為1800(30分鐘)秒,如果一個(gè)連接1800秒沒有使用,數(shù)據(jù)庫那邊就會(huì)斷掉。
testOnBorrow=false 表示使用連接池中的連接時(shí),不做檢測(cè),這個(gè)也是推薦配置,如果設(shè)置為true會(huì)影響數(shù)據(jù)庫的性能。
testWhileIdle=true 指明連接是否被空閑連接回收器進(jìn)行檢驗(yàn),如果檢測(cè)失敗,則連接將被從池中去除,和timeBetweenEvictionRunsMillis配合使用。
validationQuery=select 1 SQL查詢,用來驗(yàn)證從連接池取出的連接,驗(yàn)證連接是否有效,查詢必須是一個(gè)SQL SELECT并且必須返回至少一行記錄。
timeBetweenEvictionRunsMillis=100000 在空閑連接回收器線程運(yùn)行期間休眠的時(shí)間值,以毫秒為單位,即每100秒做一次idle連接的檢測(cè),檢測(cè)語句為validationQuery。
minEvictableIdleTimeMillis=600000 連接在池中保持空閑而不被空閑連接回收器線程,即idle連接的保存時(shí)間為600秒(10分鐘)
感覺沒有問題,每100秒就會(huì)做idle線程的檢測(cè),應(yīng)用的檢測(cè)時(shí)間600秒也小于數(shù)據(jù)庫設(shè)置的1800秒的時(shí)間,為什么還會(huì)有連接失效的異常?且報(bào)的連接失效時(shí)長越來越長。
看dbcp源碼看到還有一個(gè)參數(shù)numTestsPerEvictionRun ,在每次空閑連接回收器線程運(yùn)行時(shí)檢查的連接數(shù)量,這個(gè)參數(shù)配置了每100秒檢測(cè)的idle線程的數(shù)量。這個(gè)參數(shù)我們沒有配置,走的是默認(rèn)值。
protected int numTestsPerEvictionRun = 3;
源碼中配置的是3,就是默認(rèn)每次只檢測(cè)3個(gè)idle線程。
按照最壞的情況,最大的idle線程為800,每100秒執(zhí)行3個(gè)idle線程的判斷,判斷完所有的idle線程的狀態(tài)需要 (800/3) * 100秒=26666秒,而數(shù)據(jù)庫的超時(shí)是1800秒,這意味著如果池子滿了(或者池子中的連接數(shù)很多)的話,到所有的idle線程都檢測(cè)完成,應(yīng)用是很大概率會(huì)取到已經(jīng)失效的連接的。最早的超時(shí)連接應(yīng)該是在30分鐘之后也就是數(shù)據(jù)庫配置的1800秒
看nginx的訪問日志,當(dāng)時(shí)沒有這么一個(gè)大的量的突然訪問會(huì)把連接池打滿(或者池子中的連接增加很多),訪問量正常。
(1)應(yīng)用在16:00左右有個(gè)重啟操作,按理不會(huì)發(fā)生這種情況,以前經(jīng)常以后重啟,也不會(huì)突然連接池?cái)?shù)量上來的。
(2)想到在16:05分左右,查過一次activeMq的運(yùn)行狀態(tài)的一個(gè)操作,打jstack的時(shí)候,導(dǎo)致activeMq掛了,重啟了。這時(shí)候,應(yīng)用的量起來了,把線程數(shù)拉高了。
(3)看異常的日志第一條在16:35分左右,基本符合這個(gè)現(xiàn)象,最短的失效的線程是數(shù)據(jù)庫配置的1800秒,剛好在半個(gè)小時(shí)之后失效被使用了,報(bào)了上述異常。
網(wǎng)上大家的推薦配置是設(shè)置numTestsPerEvictionRun=maxIdle,這樣一次檢測(cè)就都可以把失效的idle都移出線程池,避免了一個(gè)高峰之后,連接池的連接已經(jīng)失效的問題。
鑒于失效的連接會(huì)被慢慢的剔除,當(dāng)時(shí)沒有做修改配置的操作,之后會(huì)把numTestsPerEvictionRun參數(shù)配置成和maxIdle一樣的值,可以避免這個(gè)問題的發(fā)生。
到此,相信大家對(duì)“如何解決dbcp連接池連接失效問題”有了更深的了解,不妨來實(shí)際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!