溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

如何解決dbcp連接池連接失效問題

發(fā)布時間:2021-07-07 14:14:05 來源:億速云 閱讀:947 作者:chen 欄目:大數(shù)據(jù)

本篇內(nèi)容主要講解“如何解決dbcp連接池連接失效問題”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實(shí)用性強(qiáng)。下面就讓小編來帶大家學(xué)習(xí)“如何解決dbcp連接池連接失效問題”吧!

一、問題出現(xiàn)

a.log的錯誤日志報(bào)了mysql的連接問題,時間在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(<generated>) ~[classes:na]

[2016-09-14 16:35:03.643]       at net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) ~[MethodProxy.class:na]

[2016-09-14 16:35:03.643]       at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:618) ~[Cglib2AopProxy$DynamicAdvisedInterceptor.class:3.1.2.RELEASE]

[2016-09-14 16:35:03.643]       at com.xx.user.friend.manager.FriendsManager$$EnhancerByCGLIB$$8999470e.getLastInviter(<generated>) ~[classes:na]

[2016-09-14 16:35:03.643]       at com.xx.user.controller.newm.NewUserMobileAPIController.getNewTipMsg(NewUserMobileAPIController.java:1977) ~[classes:na]

[2016-09-14 16:35:03.643]       at sun.reflect.GeneratedMethodAccessor104.invoke(Unknown Source) ~[na:na]

[2016-09-14 16:35:03.643]       at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.7.0_71]

[2016-09-14 16:35:03.643]       at java.lang.reflect.Method.invoke(Method.java:606) ~[na:1.7.0_71]

隨后不斷有同樣的異常報(bào)出,且時間間隔在不斷加大,到19:35的時候已經(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:

二、分析排查

1、查看現(xiàn)有配置參數(shù)

起初是認(rèn)為只有a數(shù)據(jù)庫有問題,后來發(fā)現(xiàn)b數(shù)據(jù)庫也報(bào)這個問題。判斷應(yīng)該是連接池中的連接已經(jīng)失效的問題。

(1) dbcp連接池的配置:

<bean id="webgame_ds_master" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
    <property name="driverClassName" value="xxx"/>
    <property name="url" value="xxx"/>
    <property name="username" value="xxx"/>
    <property name="password" value="xxx"/>
    <property name="maxActive" value="800"/>
    <property name="maxIdle" value="800"/>
    <property name="maxWait" value="1000"/>
    <property name="defaultAutoCommit" value="true"/>
    <property name="removeAbandoned" value="true"/>
    <property name="removeAbandonedTimeout" value="60"/>
    <property name="logAbandoned" value="false"/>
    <property name="testOnBorrow" value="false"/>
    <property name="testWhileIdle" value="true"/>
    <property name="validationQuery" value="select 1"/>
    <property name="poolPreparedStatements" value="true"/>
    <property name="timeBetweenEvictionRunsMillis" value="100000"/>
    <property name="minEvictableIdleTimeMillis" value="600000"/>
</bean>

(2)mysql數(shù)據(jù)庫配置

mysql數(shù)據(jù)庫dba那邊的超時時間設(shè)置為1800(30分鐘)秒,如果一個連接1800秒沒有使用,數(shù)據(jù)庫那邊就會斷掉。

2、dbcp參數(shù)解讀:

testOnBorrow=false 表示使用連接池中的連接時,不做檢測,這個也是推薦配置,如果設(shè)置為true會影響數(shù)據(jù)庫的性能。

testWhileIdle=true  指明連接是否被空閑連接回收器進(jìn)行檢驗(yàn),如果檢測失敗,則連接將被從池中去除,和timeBetweenEvictionRunsMillis配合使用。

validationQuery=select 1 SQL查詢,用來驗(yàn)證從連接池取出的連接,驗(yàn)證連接是否有效,查詢必須是一個SQL SELECT并且必須返回至少一行記錄。

timeBetweenEvictionRunsMillis=100000  在空閑連接回收器線程運(yùn)行期間休眠的時間值,以毫秒為單位,即每100秒做一次idle連接的檢測,檢測語句為validationQuery。

minEvictableIdleTimeMillis=600000  連接在池中保持空閑而不被空閑連接回收器線程,即idle連接的保存時間為600秒(10分鐘)

感覺沒有問題,每100秒就會做idle線程的檢測,應(yīng)用的檢測時間600秒也小于數(shù)據(jù)庫設(shè)置的1800秒的時間,為什么還會有連接失效的異常?且報(bào)的連接失效時長越來越長。

3、分析

看dbcp源碼看到還有一個參數(shù)numTestsPerEvictionRun ,在每次空閑連接回收器線程運(yùn)行時檢查的連接數(shù)量,這個參數(shù)配置了每100秒檢測的idle線程的數(shù)量。這個參數(shù)我們沒有配置,走的是默認(rèn)值。

protected int numTestsPerEvictionRun = 3;

源碼中配置的是3,就是默認(rèn)每次只檢測3個idle線程。

按照最壞的情況,最大的idle線程為800,每100秒執(zhí)行3個idle線程的判斷,判斷完所有的idle線程的狀態(tài)需要 (800/3) * 100秒=26666秒,而數(shù)據(jù)庫的超時是1800秒,這意味著如果池子滿了(或者池子中的連接數(shù)很多)的話,到所有的idle線程都檢測完成,應(yīng)用是很大概率會取到已經(jīng)失效的連接的。最早的超時連接應(yīng)該是在30分鐘之后也就是數(shù)據(jù)庫配置的1800秒

4、產(chǎn)生原因

看nginx的訪問日志,當(dāng)時沒有這么一個大的量的突然訪問會把連接池打滿(或者池子中的連接增加很多),訪問量正常。

(1)應(yīng)用在16:00左右有個重啟操作,按理不會發(fā)生這種情況,以前經(jīng)常以后重啟,也不會突然連接池?cái)?shù)量上來的。

(2)想到在16:05分左右,查過一次activeMq的運(yùn)行狀態(tài)的一個操作,打jstack的時候,導(dǎo)致activeMq掛了,重啟了。這時候,應(yīng)用的量起來了,把線程數(shù)拉高了。

(3)看異常的日志第一條在16:35分左右,基本符合這個現(xiàn)象,最短的失效的線程是數(shù)據(jù)庫配置的1800秒,剛好在半個小時之后失效被使用了,報(bào)了上述異常。

5、解決

     網(wǎng)上大家的推薦配置是設(shè)置numTestsPerEvictionRun=maxIdle,這樣一次檢測就都可以把失效的idle都移出線程池,避免了一個高峰之后,連接池的連接已經(jīng)失效的問題。

     鑒于失效的連接會被慢慢的剔除,當(dāng)時沒有做修改配置的操作,之后會把numTestsPerEvictionRun參數(shù)配置成和maxIdle一樣的值,可以避免這個問題的發(fā)生。

到此,相信大家對“如何解決dbcp連接池連接失效問題”有了更深的了解,不妨來實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI