Вот среда:
- Java 5
- Веб-приложение, работающее в Tomcat 6.0.18 в Windows (не уверенная версия)
- База данных: SQLServer 2008 R2
- Драйвер JDBC: jTDS 1.2.5
- Поставщик пула соединений: C3P0 0.9.1.2
Я пытаюсь отладить проблему, связанную с клиентомиметь.По сути, каждые пару недель наше веб-приложение блокируется на своем сервере, и они не могут получить к нему доступ.Перезапуск устраняет проблему.Дальнейшее расследование показывает, что причина того, что все заблокировано, заключается в том, что все ожидает подключения к базе данных для возврата.Я думаю, что проблема, скорее всего, связана с SQL Server, а не с C3P0.
Я считаю, что происходит то, что «запрос на проверку простоя» в C3P0 зависает.Запрос выглядит так:
select * from c3p0_connection_test_table
Похоже, этот запрос выполняется, и результат никогда не возвращается.Вот что я вижу в моей ветке дампа.Обратите внимание на DefaultConnectionTester.activeCheckConnection()
, что является проверкой на холостом ходу:
"com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2" daemon prio=6 tid=0x0000000007c32000 nid=0x1250 runnable [0x000000001072f000]
java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.read(SocketInputStream.java:129)
at java.io.DataInputStream.readFully(DataInputStream.java:178)
at java.io.DataInputStream.readFully(DataInputStream.java:152)
at net.sourceforge.jtds.jdbc.SharedSocket.readPacket(SharedSocket.java:841)
at net.sourceforge.jtds.jdbc.SharedSocket.getNetPacket(SharedSocket.java:722)
- locked <0x000000016ac03f48> (a java.util.ArrayList)
at net.sourceforge.jtds.jdbc.ResponseStream.getPacket(ResponseStream.java:466)
at net.sourceforge.jtds.jdbc.ResponseStream.read(ResponseStream.java:103)
at net.sourceforge.jtds.jdbc.ResponseStream.peek(ResponseStream.java:88)
at net.sourceforge.jtds.jdbc.TdsCore.wait(TdsCore.java:3928)
at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java:1045)
- locked <0x000000016d965268> (a net.sourceforge.jtds.jdbc.TdsCore)
at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQLQuery(JtdsStatement.java:465)
at net.sourceforge.jtds.jdbc.JtdsStatement.executeQuery(JtdsStatement.java:1301)
at com.mchange.v2.c3p0.impl.DefaultConnectionTester.activeCheckConnection(DefaultConnectionTester.java:73)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.testPooledConnection(C3P0PooledConnectionPool.java:374)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool$1PooledConnectionResourcePoolManager.refurbishIdleResource(C3P0PooledConnectionPool.java:310)
at com.mchange.v2.resourcepool.BasicResourcePool$AsyncTestIdleResourceTask.run(BasicResourcePool.java:1999)
at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)
Но что может привести к зависанию такого простого запроса при чтении из сокета?Я не верю, что в этой таблице будет какая-либо блокировка базы данных, так как она полностью управляется C3P0 и никогда не вставляется / обновляется.Кроме того, при любых неудачных попытках получить соединения из пула (если бы это было причиной зависания), я бы ожидал где-нибудь трассировки стека.Вместо этого я вижу, что приложение просто блокируется, потому что все будущие запросы на подключение ожидают завершения этой «проверки простоя».
Вот один из потоков, ожидающих завершения «проверки простоя»:
"http-80-3" daemon prio=6 tid=0x0000000007c33800 nid=0x122c in Object.wait() [0x000000001082d000]
java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:579)
- locked <0x0000000167a88a60> (a com.mchange.v2.resourcepool.BasicResourcePool)
at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:477)
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:525)
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128)
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.getConnection(LocalDataSourceConnectionProvider.java:81)
at org.hibernate.jdbc.ConnectionManager.openConnection(ConnectionManager.java:446)
at org.hibernate.jdbc.ConnectionManager.getConnection(ConnectionManager.java:167)
at org.hibernate.jdbc.JDBCContext.connection(JDBCContext.java:142)
at org.hibernate.transaction.JDBCTransaction.begin(JDBCTransaction.java:85)
at org.hibernate.impl.SessionImpl.beginTransaction(SessionImpl.java:1354)
at org.springframework.orm.hibernate3.HibernateTransactionManager.doBegin(HibernateTransactionManager.java:555)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.getTransaction(AbstractPlatformTransactionManager.java:371)
at sun.reflect.GeneratedMethodAccessor105.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:309)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:183)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy15.getTransaction(Unknown Source)
at org.springframework.transaction.interceptor.TransactionAspectSupport.createTransactionIfNecessary(TransactionAspectSupport.java:317)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:105)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
at $Proxy79.getCrowdProperties(Unknown Source)
at com.jamasoftware.contour.gateway.crowd.CrowdSsoServices.autoLogin(Unknown Source)
at com.jamasoftware.contour.security.AutoLoginServicesManager.autoLogin(Unknown Source)
at org.springframework.security.ui.rememberme.RememberMeProcessingFilter.doFilterHttp(RememberMeProcessingFilter.java:74)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.ui.AbstractProcessingFilter.doFilterHttp(AbstractProcessingFilter.java:277)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at com.jamasoftware.contour.view.filter.CheckSetupFilter.doFilter(Unknown Source)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.concurrent.ConcurrentSessionFilter.doFilterHttp(ConcurrentSessionFilter.java:99)
at org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at com.jamasoftware.contour.view.filter.ExpirationFilter.doFilter(Unknown Source)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at com.jamasoftware.contour.view.filter.GzipFilter.doFilter(Unknown Source)
at org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
at org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:864)
at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:579)
at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1665)
at java.lang.Thread.run(Thread.java:619)
При взгляде на исходный код C3P0 две строки вверху:
at java.lang.Object.wait(Native Method)
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:579)
... происходят только тогда, когда соединение ожидает "проверки на холостом ходу".
К сожалению, это клиент, и я не могу сообщить точную информацию об окружающей среде здесь.Но любые предложения, которые я могу принять к ним во время нашего следующего звонка.
ОБНОВЛЕНИЕ :
Их приложение было снова заблокировано сегодня.Вот что мы уже пробовали:
- Они обновились до последней версии драйвера jTDS (1.2.5)
- Я установил свойство
socketTimeout
встрока подключения до 300, но драйвер все еще застрял в socketRead0 () через 5 минут - Мы изменили активный контрольный запрос с "select * from c3p0_connection_test_table" на "select 1"
- У нас естьдобавили свойства
unreturnedConnectionTimeout
и debugUnreturnedConnectionStackTraces
к C3P0 (хотя они не перехватывают разорванные соединения)
Вот все свойства соединения C3P0, которые мы установили:
<property name="minPoolSize" value="1"/>
<property name="maxPoolSize" value="30"/>
<property name="acquireIncrement" value="3"/>
<property name="automaticTestTable" value="c3p0_connection_test_table"/>
<property name="idleConnectionTestPeriod" value="30"/>
<property name="testConnectionOnCheckin" value="true"/>
<property name="testConnectionOnCheckout" value="true"/>
Одна странная вещь, которая произошла, заключалась в том, что, когда приложение было заблокировано, мы пытались войти в SQL Server Management Studio с пользователем приложения, и оно не позволило нам войти (я думаю, что это была просто обычная ошибка тайм-аута).База данных была запущена и прослушивала порт 1433 (проверено с telnet
), поэтому я думаю, что это означает, что было достигнуто максимальное количество подключений к базе данных.Однако я не уверен, поможет ли это определить причину этой проблемы.
Лиды следуют без успеха :
- Этот человек имел проблему с операционными системами и, возможно, с количеством сетевых карт на сервере
- Ответчик ниже указал мне на ошибку в более старой версии jTDS здесь
Полезные ответы могут попросить меня проверить что-либо на компьютере клиента или указать на возможную причину.Независимо от ответов, которые помогут мне отследить это, вы получите награду.