c3p0 ResourcePoolException: Attempted to use a closed or broken resource pool

com.mchange.v2.resourcepool.ResourcePoolException: Attempted to use a closed or broken resource pool
at com.mchange.v2.resourcepool.BasicResourcePool.ensureNotBroken(BasicResourcePool.java:1632) ~[c3p0-0.9.1.1.jar:0.9.1.1]
at com.mchange.v2.resourcepool.BasicResourcePool.prelimCheckoutResource(BasicResourcePool.java:524) ~[c3p0-0.9.1.1.jar:0.9.1.1]
at com.mchange.v2.resourcepool.BasicResourcePool.checkoutResource(BasicResourcePool.java:477) ~[c3p0-0.9.1.1.jar:0.9.1.1]
at com.mchange.v2.c3p0.impl.C3P0PooledConnectionPool.checkoutPooledConnection(C3P0PooledConnectionPool.java:525) ~[c3p0-0.9.1.1.jar:0.9.1.1]
at com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection(AbstractPoolBackedDataSource.java:128) [c3p0-0.9.1.1.jar:0.9.1.1]
at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111) [spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77) [spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:630) [spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:695) [spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:727) [spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:737) [spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:792) [spring-jdbc-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at com.bst.security.dao.impl.SecUsersDao.findByUserAccount(SecUsersDao.java:93) [classes/:na]
at com.bst.security.dao.impl.SecUsersDao F a s t C l a s s B y S p r i n g C G L I B FastClassBySpringCGLIB FastClassBySpringCGLIBad10f21f.invoke() [spring-core-4.1.6.RELEASE.jar:na]
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204) [spring-core-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at org.springframework.aop.framework.CglibAopProxy C g l i b M e t h o d I n v o c a t i o n . i n v o k e J o i n p o i n t ( C g l i b A o p P r o x y . j a v a : 717 ) [ s p r i n g − a o p − 4.1.6. R E L E A S E . j a r : 4.1.6. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . a o p . f r a m e w o r k . R e f l e c t i v e M e t h o d I n v o c a t i o n . p r o c e e d ( R e f l e c t i v e M e t h o d I n v o c a t i o n . j a v a : 157 ) [ s p r i n g − a o p − 4.1.6. R E L E A S E . j a r : 4.1.6. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . a o p . a s p e c t j . A s p e c t J A f t e r A d v i c e . i n v o k e ( A s p e c t J A f t e r A d v i c e . j a v a : 43 ) [ s p r i n g − a o p − 4.1.6. R E L E A S E . j a r : 4.1.6. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . a o p . f r a m e w o r k . R e f l e c t i v e M e t h o d I n v o c a t i o n . p r o c e e d ( R e f l e c t i v e M e t h o d I n v o c a t i o n . j a v a : 179 ) [ s p r i n g − a o p − 4.1.6. R E L E A S E . j a r : 4.1.6. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . a o p . i n t e r c e p t o r . E x p o s e I n v o c a t i o n I n t e r c e p t o r . i n v o k e ( E x p o s e I n v o c a t i o n I n t e r c e p t o r . j a v a : 92 ) [ s p r i n g − a o p − 4.1.6. R E L E A S E . j a r : 4.1.6. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . a o p . f r a m e w o r k . R e f l e c t i v e M e t h o d I n v o c a t i o n . p r o c e e d ( R e f l e c t i v e M e t h o d I n v o c a t i o n . j a v a : 179 ) [ s p r i n g − a o p − 4.1.6. R E L E A S E . j a r : 4.1.6. R E L E A S E ] a t o r g . s p r i n g f r a m e w o r k . a o p . f r a m e w o r k . C g l i b A o p P r o x y CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717) [spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157) [spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE] at org.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:43) [spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE] at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) [spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE] at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179) [spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE] at org.springframework.aop.framework.CglibAopProxy CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:717)[springaop4.1.6.RELEASE.jar:4.1.6.RELEASE]atorg.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)[springaop4.1.6.RELEASE.jar:4.1.6.RELEASE]atorg.springframework.aop.aspectj.AspectJAfterAdvice.invoke(AspectJAfterAdvice.java:43)[springaop4.1.6.RELEASE.jar:4.1.6.RELEASE]atorg.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)[springaop4.1.6.RELEASE.jar:4.1.6.RELEASE]atorg.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)[springaop4.1.6.RELEASE.jar:4.1.6.RELEASE]atorg.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)[springaop4.1.6.RELEASE.jar:4.1.6.RELEASE]atorg.springframework.aop.framework.CglibAopProxyDynamicAdvisedInterceptor.intercept(CglibAopProxy.java:653) [spring-aop-4.1.6.RELEASE.jar:4.1.6.RELEASE]
at com.bst.security.dao.impl.SecUsersDao E n h a n c e r B y S p r i n g C G L I B EnhancerBySpringCGLIB EnhancerBySpringCGLIB7a4688bc.findByUserAccount() [spring-core-4.1.6.RELEASE.jar:na]
at com.bst.security.sec.CustomUserDetailsService.loadUserByUsername(CustomUserDetailsService.java:42) [classes/:na]
at org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper.loadUserDetails(UserDetailsByNameServiceWrapper.java:53) [spring-security-core-4.0.0.RELEASE.jar:na]
at org.springframework.security.cas.authentication.CasAuthenticationProvider.loadUserByAssertion(CasAuthenticationProvider.java:214) [spring-security-cas-4.0.0.RELEASE.jar:na]
at org.springframework.security.cas.authentication.CasAuthenticationProvider.authenticateNow(CasAuthenticationProvider.java:159) [spring-security-cas-4.0.0.RELEASE.jar:na]
at org.springframework.security.cas.authentication.CasAuthenticationProvider.authenticate(CasAuthenticationProvider.java:142) [spring-security-cas-4.0.0.RELEASE.jar:na]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:167) [spring-security-core-4.0.0.RELEASE.jar:na]
at org.springframework.security.authentication.ProviderManager.authenticate(ProviderManager.java:192) [spring-security-core-4.0.0.RELEASE.jar:na]
at org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter$AuthenticationManagerDelegator.authenticate(WebSecurityConfigurerAdapter.java:446) [spring-security-config-4.0.0.RELEASE.jar:na]

搜索该错误发现以下解决方法:



出现该问题的原因是c3p0的自动重连机制:
1、C3P0容错和自动重连与以下配置参数有关:
breakAfterAcquireFailure :true表示pool向数据库请求连接失败后标记整个pool为block并close,就算后端数据库恢复正常也不进行重连,客户端对pool的请求都拒绝掉。false表示不会标记 pool为block,新的请求都会尝试去数据库请求connection。默认为false。因此,如果想让数据库和网络故障恢复之后,pool能继续请求正常资源必须把此项配置设为false。
idleConnectionTestPeriod :C3P0会有一个Task检测pool内的连接是否正常,此参数就是Task运行的频率。默认值为0,表示不进行检测。
testConnectionOnCheckout :true表示在每次从pool内checkout连接的时候测试其有效性,这是个同步操作,因此应用端的每次数据库调用,都会先通过测试sql测试其有效性,如果连接无效,会关闭此连接并剔除出pool,并尝试从pool内取其他连接,默认为false,此特性要慎用,会造成至少多一倍的数据库调用。
testConnectionOnCheckin :true表示每次把连接checkin到pool里的时候测试其有效性,因为是个事后操作,所以是异步的,应用端不需要等待测试结果,但同样会造成至少多一倍的数据库调用。
acquireRetryAttempts 和acquireRetryDelay :pool请求取连接失败后重试的次数和重试的频率。请求连接会发生在pool内连接少于min值或则等待请求数>池内能提供的连接数。
automaticTestTable 、connectionTesterClassName 、preferredTestQuery :表示测试方式,默认是采用 DatabaseMetaData.getTables()来测试connection的有效性,但可以通过以上配置来定制化测试语句,通过其名字就很好理解其含义,无需过多解释。
maxIdleTime 和 maxConnectionAge :表示connection的时效性,maxIdleTime和maxConnectionAge不同之处在于, maxIdleTime表示idle状态的connection能存活的最大时间,而 maxConnectionAge表示 connection能存活的绝对时间
2、应用端getConnection抛出exception时, C3P0会测试其connection的有效性,并根据状态处理此connection,但应用端不会重调。
3、无论是网络问题还是远端数据库服务器,就算恢复正常后,客户端pool内其已存在的connection都会失效,要保证应用端调用无误,必须在checkout到应用端之前刷新这些无效connection
4、breakAfterAcquireFailure=false是关键。如果 breakAfterAcquireFailure=true ,一旦pool向数据库请求连接失败,就会标记pool block并关闭pool,这样无论数据库是否恢复正常,应用端都无法从pool拿到连接
5、要想保证网络和数据库瞬间的失效100%不会造成应用端getConnection失败必须开启 testConnectionOnCheckout。但此特性的代价巨大,建议在应用端做容错。
6、推荐使用 idleConnectionTestPeriod。可以根据应用调用频率权衡一个检查pool的频率,这样可以在保证性能损耗不大情况下,尽可能的保证pool内connection的有效性
7、若嫌DatabaseMetaData.getTables()性能不好,可以尝试通过配置automaticTestTable、connectionTesterClassName、preferredTestQuery来找到一个性能最好的测试语句,只要能验证connection有效就行
综上所述,要想保证性能的前提下,本人推荐的配置组合如下:
breakAfterAcquireFailure: false
testConnectionOnCheckout: false
testConnectionOnCheckin: false
idleConnectionTestPeriod: 60
acquireRetryAttempts: 10
acquireRetryDelay: 1000
但需要注意的是以上的配置不能保证100%应用端getConnection无误,如果应用端不能发生getConnection错误,需要自行考虑容错和重试机制。

在以上配置下,当网络或数据库发生瞬间变动的情况下,会有如下事情发生:

自动测试idleConnection的 task轮训检测pool,对每个connction通过DatabaseMetaData.getTables()来测试有效性,并剔除无效连接。

根据请求情况和配置,pool向数据库请求新连接并加入池内

应用端getConnection->是否发生异常->如果发生异常,检验其有效性,并剔除出pool->如果没有发生异常(自动检查task之前已检测),调用成功

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值