2

我正在 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

对我的 Web 服务的每个请求都至少会访问数据库几次。在运行大约 200 个请求/分钟的负载测试 10 分钟后,我发现大部分时间都花在了

com.mchange.v2.c3p0.impl.AbstractPoolBackedDataSource.getConnection

我猜它正在等待连接池中的连接?有趣的部分是随着我的增加

hibernate.c3p0.maxPoolSize, 40

性能更差(在同一个调用中等待时间更长getConnection。在测试过程中,我可以看到c3p0MySQL 服务器上确实打开了最大连接数(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, 25to增加hibernate.c3p0.maxPoolSize, 30,但在之后下降hibernate.c3p0.maxPoolSize, 35。我的价值观离我们很远吗?

谢谢!

4

1 回答 1

1

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

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

鉴于您的设置,辅助线程不应该有太多工作要做,除非 maxStatementsPerConnection 太小。如果您的应用程序有超过 5 个频繁运行的 PreparedStatements,那么您最终将通过 Statements 搅动,并将辅助线程与 Statement close() 任务捆绑在一起。您可以尝试使此值更大。它应该大约(向上取整)您的应用程序持续使用的不同 PreparedStatements 的数量。(您可以忽略单个或很少使用的 PreparedStatements,例如在设置或清理中涉及。)再次,监视帮助线程正在执行的操作将为您提供有关这是否是问题的信息。(您会看到备份的 Statement close() 任务。)

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

祝你好运!

于 2013-08-26T05:55:43.280 回答