我在Heroku上运行Web服务并使用New Relic来监控其性能。我在顶部使用MySQL和Hibernate。我的非默认c3p0设置如下
hibernate.c3p0.maxStatementsPerConnection, 5
hibernate.c3p0.maxPoolSize, 35
hibernate.c3p0.minPoolSize, 5
hibernate.c3p0.initialPoolSize, 10
hibernate.c3p0.acquireIncrement, 10
我的网络服务的每一个请求都至少会对数据库进行一次攻击。在运行大约200个请求/分钟的负载测试10分钟后,我看到大部分时间花在了
上com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection
我猜他在等待连接池中的连接?有趣的是我增加了
hibernate.c3p0.maxPoolSize, 40
性能更差(在同一getConnection
次呼叫中等待时间更长。在测试期间,我可以看到MySQL服务器上确实打开了c3p0
个连接的最大数量(最大连接集)在MySQL的结尾是300
,绝对没有用尽。)
我的所有数据库函数都使用相同的格式
public void executeTransaction( Session session, IGenericQuery<T> query, T entity )
{
Transaction tx = null;
try
{
tx = session.beginTransaction();
query.execute( session, entity );
tx.commit();
}
catch ( RuntimeException e )
{
try
{
tx.rollback();
}
catch ( RuntimeException e2 )
{
}
throw e;
}
finally
{
if ( session != null )
{
session.close();
}
}
}
所以我确定所有会话都已关闭,这应该转化为关闭关闭。为什么等待时间会增加最大连接数?性能似乎从hibernate.c3p0.maxPoolSize, 25
增加到hibernate.c3p0.maxPoolSize, 30
,但在hibernate.c3p0.maxPoolSize, 35
之后下降。我的价值观远远不够?
谢谢!
答案 0 :(得分:1)
作为猜测,我会尝试增加numHelperThreads。你的负担很重;也许c3p0的管理线程正在备份。 (如果你转储堆栈跟踪或者使用JMX监视c3p0,你应该能够看到这个。如果你有足够的帮助程序线程,它们通常应该是idle(),wait()ing。如果它们得到备份,你将会看到它们主要是活动的和可运行的,并且通过JMX,你会看到排队的任务。)
辅助线程不足与使用maxPoolSize观察到的性能越来越差的性能一致。最初你得到你想要的东西,准备好更多的连接,但是助手线程无法跟上并添加更多连接只会让事情变得更糟。
根据你的设置,辅助线程不应该做太多工作,除非maxStatementsPerConnection太小。如果您的应用程序有超过5个经常运行的PreparedStatements,那么您将最终通过语句进行搅拌并使用Statement close()任务绑定帮助程序线程。您可以尝试将此值放大。它应该大致(四舍五入)您的申请持续使用的不同PreparedStatements的数量。 (您可以忽略单个或很少使用的PreparedStatements,例如在设置或清理中涉及。)再次,监视哪些帮助程序线程将为您提供有关这是否是问题的信息。 (你会看到备份的Statement close()任务。)
所以,要尝试的事情:增加numHelperThreads,增加maxStatementsPerConnection(或将其设置为零,完全关闭Statement缓存。)
祝你好运!