您好,登錄后才能下訂單哦!
本篇內容主要講解“如何解決dbcp連接池連接失效問題”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“如何解決dbcp連接池連接失效問題”吧!
a.log的錯誤日志報了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] |
隨后不斷有同樣的異常報出,且時間間隔在不斷加大,到19:35的時候已經是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: |
起初是認為只有a數據庫有問題,后來發現b數據庫也報這個問題。判斷應該是連接池中的連接已經失效的問題。
<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> |
mysql數據庫dba那邊的超時時間設置為1800(30分鐘)秒,如果一個連接1800秒沒有使用,數據庫那邊就會斷掉。
testOnBorrow=false 表示使用連接池中的連接時,不做檢測,這個也是推薦配置,如果設置為true會影響數據庫的性能。
testWhileIdle=true 指明連接是否被空閑連接回收器進行檢驗,如果檢測失敗,則連接將被從池中去除,和timeBetweenEvictionRunsMillis配合使用。
validationQuery=select 1 SQL查詢,用來驗證從連接池取出的連接,驗證連接是否有效,查詢必須是一個SQL SELECT并且必須返回至少一行記錄。
timeBetweenEvictionRunsMillis=100000 在空閑連接回收器線程運行期間休眠的時間值,以毫秒為單位,即每100秒做一次idle連接的檢測,檢測語句為validationQuery。
minEvictableIdleTimeMillis=600000 連接在池中保持空閑而不被空閑連接回收器線程,即idle連接的保存時間為600秒(10分鐘)
感覺沒有問題,每100秒就會做idle線程的檢測,應用的檢測時間600秒也小于數據庫設置的1800秒的時間,為什么還會有連接失效的異常?且報的連接失效時長越來越長。
看dbcp源碼看到還有一個參數numTestsPerEvictionRun ,在每次空閑連接回收器線程運行時檢查的連接數量,這個參數配置了每100秒檢測的idle線程的數量。這個參數我們沒有配置,走的是默認值。
protected int numTestsPerEvictionRun = 3;
源碼中配置的是3,就是默認每次只檢測3個idle線程。
按照最壞的情況,最大的idle線程為800,每100秒執行3個idle線程的判斷,判斷完所有的idle線程的狀態需要 (800/3) * 100秒=26666秒,而數據庫的超時是1800秒,這意味著如果池子滿了(或者池子中的連接數很多)的話,到所有的idle線程都檢測完成,應用是很大概率會取到已經失效的連接的。最早的超時連接應該是在30分鐘之后也就是數據庫配置的1800秒
看nginx的訪問日志,當時沒有這么一個大的量的突然訪問會把連接池打滿(或者池子中的連接增加很多),訪問量正常。
(1)應用在16:00左右有個重啟操作,按理不會發生這種情況,以前經常以后重啟,也不會突然連接池數量上來的。
(2)想到在16:05分左右,查過一次activeMq的運行狀態的一個操作,打jstack的時候,導致activeMq掛了,重啟了。這時候,應用的量起來了,把線程數拉高了。
(3)看異常的日志第一條在16:35分左右,基本符合這個現象,最短的失效的線程是數據庫配置的1800秒,剛好在半個小時之后失效被使用了,報了上述異常。
網上大家的推薦配置是設置numTestsPerEvictionRun=maxIdle,這樣一次檢測就都可以把失效的idle都移出線程池,避免了一個高峰之后,連接池的連接已經失效的問題。
鑒于失效的連接會被慢慢的剔除,當時沒有做修改配置的操作,之后會把numTestsPerEvictionRun參數配置成和maxIdle一樣的值,可以避免這個問題的發生。
到此,相信大家對“如何解決dbcp連接池連接失效問題”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。