c3p0 getConnection在连接数增加时挂起

时间:2013-08-26 01:27:25

标签: java mysql hibernate heroku c3p0

我在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之后下降。我的价值观远远不够?

谢谢!

1 个答案:

答案 0 :(得分:1)

作为猜测,我会尝试增加numHelperThreads。你的负担很重;也许c3p0的管理线程正在备份。 (如果你转储堆栈跟踪或者使用JMX监视c3p0,你应该能够看到这个。如果你有足够的帮助程序线程,它们通常应该是idle(),wait()ing。如果它们得到备份,你将会看到它们主要是活动的和可运行的,并且通过JMX,你会看到排队的任务。)

辅助线程不足与使用maxPoolSize观察到的性能越来越差的性能一致。最初你得到你想要的东西,准备好更多的连接,但是助手线程无法跟上并添加更多连接只会让事情变得更糟。

根据你的设置,辅助线程不应该做太多工作,除非maxStatementsPerConnection太小。如果您的应用程序有超过5个经常运行的PreparedStatements,那么您将最终通过语句进行搅拌并使用Statement close()任务绑定帮助程序线程。您可以尝试将此值放大。它应该大致(四舍五入)您的申请持续使用的不同PreparedStatements的数量。 (您可以忽略单个或很少使用的PreparedStatements,例如在设置或清理中涉及。)再次,监视哪些帮助程序线程将为您提供有关这是否是问题的信息。 (你会看到备份的Statement close()任务。)

所以,要尝试的事情:增加numHelperThreads,增加maxStatementsPerConnection(或将其设置为零,完全关闭Statement缓存。)

祝你好运!