java连接池性能测试报告

  当前问题

1  高并发异常

         目前应用的 Proxool 连接池,在高并发情况下会出现:

         1. DataSource.getConnection() 方法会根据 ProxoolDataSource.simultaneousBuildThrottle 限制连接创建的并发,超出限制将抛出 java.sql.SQLException: We are already in the process of making 11 connections and the number of simultaneous builds has been throttled to 10 异常;

         2. 当满足条件 “connectionCount >= getDefinition().getMaximumConnectionCount() && connectionPool.getAvailableConnectionCount() < 1” 时, DataSource.getConnection() 方法将抛出 java.sql.SQLException: Couldn't get connection because we are at maximum connection count (200/200) and there are none available 异常;

         3. 当满足条件 connectionCount >= getDefinition().getMaximumConnectionCount() ” DataSource.getConnection() 方法将抛出 java.sql.SQLException: org.logicalcobwebs.proxool.ProxoolException: ConnectionCount is 200. Maximum connection count of 200 cannot be exceeded. 异常。

         第一种异常可以修改配置文件,增加 simultaneousBuildThrottle 避免,但后两种情况只能增加数据库连接。并发量大于数据库连接数,必然会报后两种异常。可见 Proxool 并未具有完整的连接池实现,其尚未具有处理高并发应用的能力。

 

2  多连接数

         为减少以上情况的发生,必须设置 Proxool 数据库连接数大于等于业务线程数

         当业务线程数为 300 时,数据库连接池的最大连接数必须大于三百。这里说 大于 ,意义是即使业务线程数为 300 、数据库连接数为 300 ,也不能保证不报后两种异常。

         维持过多的连接对于数据可游戏服务器都有一定的资源浪费,而且有碍新的服务器分布式、集群的实现。

  替代方案

         经过网上搜索,找到其他连接池实现: DBCP Tomcat JDBC Pool DBPool C3P0 BoneCP Db Connection Broker MiniConnectionPoolManager

         DBCP Tomcat6 默认连接池,但 1.2 版本倍受缓慢诟病,最新版本为 1.4 Tomcat JDBCPool Tomcat Tomcat7 中保留 DBCP 连接池以兼容使用 DBCP 连接池的已有应用,并提供新的 Tomcat JDBC Pool 作为 DBCP 的可选替代,修改一行配置文件即可启用 [1] DBPool ObjectWeb 开源产品,但多年未维护。 C3P0 Hibernate 默认连接池。 BoneCP 为新兴产品,网上评价极高。

         Db Connection Broker MiniConnectionPoolManager 是两个轻量级连接池,实现只有 1 个类。

1  API

         其中 DBCP C3P0 已被广泛应用,可以认为稳定可靠。

         Db Connection Broker MiniConnectionPoolManager 未提供 javax.sql.DataSource 接口实现,不予考虑。

         经过对 API 和部分代码的研究,除 Proxool 以外所有连接池均有无可分配链接时让线程等待的功能,并提供超时参数或等价替代方案,超时未取得连接则抛出异常。

2  性能

         为测试连接池性能,撰写测试程序,多线程无延迟持续查询“ select 1 ”,分别测试单位时间内查询次数。

1 在双核、 3G 内存,最大连接 5 ,发连接改为 4 BoneCP 2 区,不计算预热阶段,持续时间 1 分钟:


java连接池性能测试报告

Proxool 虽然在性能上远超 DBPool ,但第一次测试报 3 次异常,第三次测试报 2 次异常,均为第三种异常“ ProxoolException: ConnectionCount is 5. Maximum connection count of 5 cannot be exceeded. ”,线程数小于连接数竟然还报错,不可容忍; C3P0 明显领先; DBCP 紧随其后,可见两大著名连接池果然给力;新星 BoneCP 一度超越 DBCP ,平均成绩名列第三; TomcatPool 排在第四,但性能稳定。

 

2 在双核、 3G 内存,最大连接 5 ,并发线程 500 BoneCP 2 区,持续三分钟,不计算预热阶段,测试三次,测试结果如下:


java连接池性能测试报告

 

TomcatPool 在高并发低连接数情况下,性能稍强于 DBCP ,但不明显; BoneCP Tomcat DBCP 甩在后面; C3P0 表现一般; DBPool 稳稳淘汰。

 

3 4 cpu 1000 线程、 200 连接、 BoneCP 100 区,连续 15 分钟,不计算预热阶段,测试次数结果如下( DBPool 在多次测试结果中远远落后于其他,为节约时间这次未参与测试):


java连接池性能测试报告

可见 DBCP 在高并发、高连接数情况下,查询量远远超过位于第三代 C3P0 并甩开后两名十万次左右; BoneCP TomcatPool 性能接近; C3P0 远远落后前三者。

 

         高并发时 visualvm 线程状态记录如下:


java连接池性能测试报告
 
java连接池性能测试报告
 
java连接池性能测试报告
 
java连接池性能测试报告
 
java连接池性能测试报告

         从线程状态记录中可见, DBCP TomcatPool 可以快速的交付连接,在途中形成琐碎的绿色条带, DBCP 图中有 3 处可忽略的红色条带,而 TomcatPool 在线程启动时被锁一段时间。 C3P0 大量使用同步锁,产生了大量的红色条带。QueryThread线程为 BoneCP查询线程, 没有使用同步锁。 DBPool 基本上全部使用同步机制,导致大量线程等待。

由于没有对源代码深入分析,尚不知 BoneCP 为何落后 TomcatPool DBCP

 

         综上所述,新版 DBCP 连接池仍然是一款高性能的杰作。

 

后记

以上列出仅为典型测试数据,本次测试实际耗时将近一周,大量数据未能展示。

在一些记录中显示,项目工程中包含的 DBCP 1.2 的性能确实不如人意,仅仅超过 DBPool 这款同样古老的同胞,但新版 DBCP 1.4+commons pool 1.6 的绝佳配合将 DBCP 的性能推进到一个新的高峰。下图为 DBCP 1.2 的线程状态:


java连接池性能测试报告

BoneCP 这一新兴在速度上给人相当大的惊喜,但其内存回收依赖于独立线程,默认情况下 BoneCP 会启动很多附加线程,其中大部分线程将保留到程序结束。利用其它线程回收未关闭的 connection statement result 带来的结果是,如果未关闭 statement result ,而只关闭 connection ,那么 statement result 将延迟回收,在如此高并发、高频率的测试中这样的延迟回收将导致一分钟之内将 2G 内存装满、程序崩溃。

下图为部分附加线程,实际情况要好长的列表,截图不下来了。。


java连接池性能测试报告

下图为业务线程结束,并且已经对数据源 close 操作之后,仍然有部分线程持续运行。

 
java连接池性能测试报告

 

下图右上角图像显示 proxool 的内存占用大于其他,而右下角图像显示 BoneCP 线程数远远大于其他。


java连接池性能测试报告

 



[1]      http://tomcat.apache.org/tomcat-7.0-doc/jdbc-pool.html

你可能感兴趣的:(java)