【问题标题】:How to tweak c3po & mysql tandem for performance?如何调整 c3po 和 mysql 串联以提高性能?
【发布时间】:2015-02-26 21:41:32
【问题描述】:

进一步的问题是:为什么 com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable() 会消耗如此多的执行时间?还有 - 如何解决这个问题?

现在让我给你详细说明...

背景: 我有 Spring MVC java web 应用程序,它使用 SpringJDBC 进行数据访问。数据源配置如下:

<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
    <property name="driverClass" value="${jdbc.driverClassName}" />
    <property name="jdbcUrl" value="${jdbc.databaseurl}" />
    <property name="user" value="${jdbc.username}" />
    <property name="password" value="${jdbc.password}" />
    <property name="testConnectionOnCheckout" value="${c3po.testConnectionOnCheckout}" />
    <property name="minPoolSize" value="${c3po.minPoolSize}" />
    <property name="maxPoolSize" value="${c3po.maxPoolSize}" />
    <property name="checkoutTimeout" value="${c3po.checkoutTimeout}" />
    <property name="maxStatementsPerConnection" value="${c3po.maxStatementsPerConnection}" />
</bean>

相关属性:

jdbc.driverClassName=com.mysql.jdbc.Driver
jdbc.databaseurl=jdbc:mysql://localhost:3306/timesheet?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
jdbc.username=root
jdbc.password=somepassword
c3po.testConnectionOnCheckout=true
c3po.minPoolSize=5
c3po.maxPoolSize=200
c3po.checkoutTimeout=30000
c3po.maxStatementsPerConnection=50

当前意图: 准备公共可用性申请。所以我创建了一个非常简单的 JMeter 测试计划,它使用 500 个并发线程一次又一次地简单地打开应用程序的索引页面。

问题: 是不是我看到性能非常差,每秒大约 140 个请求,平均请求时间为 1700 毫秒,这是完全不可接受的。 请注意,在正常情况下没有负载测试,这样的请求大约需要 6 毫秒。 所以我做了什么 - 我运行了 jvisualvm,并进行了分析。 看起来它是消耗最多执行时间的 com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable() 。

问题: 为什么 com.mchange.v2.resourcepool.BasicResourcePool.awaitAvailable() 会消耗如此多的执行时间?还有 - 如何解决这个问题?

注意 1:当然我正在考虑添加更多缓存逻辑以避免调用数据库,但现在我对 c3po 和 mysql 优化更感兴趣。

注意 2:我运行的是 Windows 7 x64,它不是生产环境(它将是 CentOS),但仍然拥有顶级 i7 英特尔处理器和 SSD 磁盘,我期望更高的性能 =)

【问题讨论】:

  • 不要使用 C3P0 :)。我会推荐HikariCP 我有更好的经验。此外,您的池畔没有意义,太大的池会影响您的表现,nice read here。接下来在不同的硬件和操作系统上运行测试,就像在生产中一样,恕我直言,这是一个无用的练习,因为操作系统可能会产生相当大的影响。
  • 感谢您的建议。我刚试过。嗯......显然它显示了更好的性能!但是应用程序现在没有响应来自浏览器的请求 =) 不知道为什么,首先猜测 - tomcat 已经死了 =)
  • 您确定它没有回答还是您的测试可能有缺陷?正常的申请能用吗?
  • 是的,Firefox 显示空白页。我认为这与测试环境有关,事实上我在运行 tomcat 的同一台机器上运行 Jmeter。 Jmeter说“连接关闭”,可能与操作系统的限制有关。

标签: java mysql spring c3p0 spring-jdbc


【解决方案1】:

所以有一个基本问题:

您有一个最大连接数为 200 个的池。您有 500 个并发客户端。如果数据库操作比您的应用程序正在执行的任何其他操作慢得多(并不罕见,因为它是网络 IO),对于使用数据库连接的每两个客户端线程,将有三个 wait()ing,例如在等待可用()。如果这是您问题的核心,它将与池无关,并且只能通过增加 maxPoolSize 来解决。

但也存在特定于 c3p0 的问题。 c3p0 是一个比大多数“厚”的池,特别是比非常轻量级的 Hikari 厚。 (我希望)在健壮性和可配置性方面有优势,但潜在的性能成本。在 c3p0 下,您可以采取以下措施来提高此应用程序的性能:

1) 将numHelperThreads 设置为高于其默认值 3 的值,可能为 10 或 20。c3p0 将许多维护和测试任务委托给辅助线程池。由于您给它带来的负载,只有 3 个辅助线程,这些任务可能会得到备份,从而减慢连接签入的完成速度,从而减慢新客户端的可用性。

2) 优化您的测试制度。正如 geert3 所说,除非您使用最新的 c3p0 [c3p0-0.9.5-pre10] 和兼容 JDBC4 的驱动程序,否则您将退回到非常慢的测试。您还在结帐时进行测试,这会减慢每个客户端线程的速度。请参阅here 获取一些建议。

3) 设置更大的minPoolSize 和/或acquireIncrement。您的池从很小的大小开始,并以 3 个连接的批次增长。在这些设置下需要一些时间才能达到 200 的完整 maxPoolSize(这仍然不足以在没有等待的情况下覆盖您的负载)。在池从小到大的过渡期间,您的 500 个客户将花费大量时间等待()。

【讨论】:

    【解决方案2】:

    确保定义preferredTestQuery,例如SELECT 1

    来自http://www.mchange.com/projects/c3p0/#preferredTestQuery

    首选测试查询 默认值:空 定义将为所有连接测试执行的查询, 如果默认 ConnectionTester (或其他一些实现 QueryConnectionTester,或者更好的 FullQueryConnectionTester)正在被使用。 定义一个将在您的数据库中快速执行的preferredTestQuery 可能 大大加快了连接测试。(如果没有设置 preferredTestQuery,则 默认 ConnectionTester 在 Connection 上执行 getTables() 调用 数据库元数据。根据您的数据库,这可能会执行得更慢 比“正常”的数据库查询。) ……

    【讨论】:

    • 太棒了。这只会使性能提高 3 倍。
    • 如果你也将mysql MAX_CONNECTIONS 增加到500 会更好。我会将此标记为答案,但下面史蒂夫沃尔德曼的建议也非常有用。
    猜你喜欢
    • 1970-01-01
    • 2023-02-26
    • 2012-10-17
    • 2015-02-26
    • 1970-01-01
    • 2016-08-12
    • 2015-09-16
    • 2017-02-28
    • 1970-01-01
    相关资源
    最近更新 更多