2012-11-04 127 views
2

我的应用程序每分钟只有一个http请求被查询。 当c3p0运行CullExpired和其他后台线程时,应用程序暂时超时并且无响应。这个问题随机发生并且偶尔发生。所有应用程序超时时的实例,我看到c3p0后台线程正在尝试执行清理或清除空闲连接。这种情况非常随机,日志中没有其他例外。一段时间后,应用程序会自动恢复并恢复处理。有没有人遇到过这样的问题。c3p0导致应用程序在偶发时间间隔超时

c3p0 version is <version>0.9.1.2</version> 
    hibernate version is <version>3.3.2.GA</version> 

我C3P0的配置是:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" 
     destroy-method="close" 
     p:driverClass="#{['app.jdbc.driverClassName']}" 
     p:jdbcUrl="#{['app.jdbc.url']}" 
     p:user="#{['app.jdbc.username']}" 
     p:password="#{['app.jdbc.password']}" 
     p:acquireIncrement="5" 
     p:idleConnectionTestPeriod="80" 
     p:maxAdministrativeTaskTime="600" 
     p:numHelperThreads="10" 
     p:maxIdleTime="60" 
     p:maxPoolSize="20" 
     p:maxStatements="30" 
     p:minPoolSize="10" /> 

回答

2

C3P0的后台线程都始终围绕;他们在一个线程池中运行。您已将该池的大小设置为10个线程(c3p0.numHelperThreads)。如果您检查堆栈转储,在您的配置下,您会看到像CullExpired这样的c3p0任务非常频繁地运行。这些频率与配置设置的数量级相同,这会使资源过期。在你的情况下,maxIdleTime是60秒,所以剔除任务可能每20秒左右运行一次。 c3p0的管理任务经过精心设计,不会在IO期间保持锁定状态,并且通常轻量级,并且不会尽可能与其他工作竞争。所以,有些奇怪的事情正在发生,如果这些管理任务导致你的挂起。但很难区分原因和巧合之间的区别:c3p0的助手线程总是在周围,管理任务经常运行。

maxIdleTime是您的问题的一种可能的解释。你使用的配置不是很好。每分钟一个客户端连接对于c3p0来说是一个超小的负载,但是您有一个10个连接的minPoolSize。所以,c3p0抓住10个连接,保持它们约一分钟,然后过期并重新获得它们,这是一个很大的问题。您80秒的idleConnectionTestPeriod无用:空闲连接永远不会被测试,因为它们在闲置60秒后,在测试期结束之前会过期。我也会将acquireIncrement降回默认值3.

我想尝试一个更好的配置,看看是否解决了这个问题。考虑到你描述的负载,我将minPoolSize设置为默认值3,并将numHelperThreads设置为3.作为第一遍,我将maxIdleTime设置为默认值零,但将testConnectionOnCheckout设置为true。这是连接测试的最简单和最可靠的形式,但它会影响客户可见的性能成本。为了最大限度地降低成本,您应该设置preferredTestQuery,而不是依靠慢速默认Connection测试。通常“SELECT 1”可以工作,但它可能取决于您的数据库/ JDBC驱动程序。如果事情看起来不错,你可能会更大胆,尝试一个稍微更高性能,稍不稳定的连接测试策略:将idleConnectionTestPeriod设置为一个相对较小的值(例如30),并将testConnectionOnCheckin设置为true(并且将testConnectionOnCheckout恢复为其默认值false) 。请参阅[http://www.mchange.com/projects/c3p0/#configuring_connection_testing]

此外,我现在会将语句缓存关闭(将maxStatements设置为0),并在事情稳定时再打开它以测试它是否会改进应用程序的性能。 [这是一个如果 - 见http://www.mchange.com/projects/c3p0/#known_shortcomings]

我也建议更新到最新版本的c3p0 [c3p0-0.9.2-pre5]。在0.9.2版本中,连接获取更加轻量级,并且您的问题的一部分可能与您每1分钟刷新和重新获取周期有关。总的来说,我认为0.9.2-pre系列现在非常稳定,值得使用。

我希望这有助于!

+0

谢谢史蒂夫。我相应地更改了配置。我认为可疑的是gettables()调用在夜晚当各种数据库进程运行导致应用程序超时的一些请求变得更慢。所以我添加了preferredTestQuery选择1和testConnectionOnCheckout为true。 – user1797433

+0

我的当前配置:<豆ID = “数据源” 类= “com.mchange.v2.c3p0.ComboPooledDataSource” \t \t破坏法= “接近” \t \t号码:driverClass =“#{['app.jdbc .driverClassName']}” \t \t号码:JDBCURL = “#{[ 'app.jdbc.url']}” \t \t号码:用户= “#{[ 'app.jdbc.username']}” \t \t号码:密码= “#{[ 'app.jdbc.password']}” \t \t号码:acquireIncrement = “5” \t \t号码:numHelperThreads = “3” \t \t号码:preferredTestQuery = “SELECT 1” \t \t号码:testConnectionOnCheckout = “真” \t \t号码:maxIdleTime = “0” \t \t号码:maxPoolSize = “40” \t \t号码:了MinPoolSize = “5” /> – user1797433

+0

看起来好多了。它会影响你的问题吗? (顺便说一句,最好确保你得到了你认为你正在设置的配置,特别是因为你的配置环境是复杂的替代等。c3p0 PooledDataSources在INFO级别转储配置到你的日志。注意上面我的目的是为了简化,如果你使用的连接超时的数据库 - 例如mysql - 设置一个有限但大的maxIdleTime,如3600,可能是最好的。) –

相关问题