You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java连接池性能检测:如何对比不同连接池的性能差异

Java连接池性能检测方案与代码

为什么单线程循环测不出差异

单线程下,连接池的连接复用、并发控制优势无法体现,所有操作串行执行,耗时差异被完全抹平。要测出真实性能差异,必须模拟高并发场景,同时聚焦以下核心指标:

  • 连接获取的平均/峰值耗时
  • 并发吞吐量(每秒处理的连接请求数)
  • 连接池资源耗尽时的等待/拒绝表现
  • 连接归还后的复用效率

通用检测框架代码

下面使用JMH(Java官方推荐的微基准测试工具)来实现,它能规避JIT优化、测量误差等问题,同时模拟多线程并发场景,对比HikariCP、Apache Commons DBCP2、Tomcat JDBC Pool这几款主流连接池。

1. Maven依赖配置

<dependencies>
    <!-- JMH核心依赖 -->
    <dependency>
        <groupId>org.openjdk.jmh</groupId>
        <artifactId>jmh-core</artifactId>
        <version>1.37</version>
    </dependency>
    <dependency>
        <groupId>org.openjdk.jmh</groupId>
        <artifactId>jmh-generator-annprocess</artifactId>
        <version>1.37</version>
        <scope>provided</scope>
    </dependency>
    <!-- 各连接池依赖 -->
    <dependency>
        <groupId>com.zaxxer</groupId>
        <artifactId>HikariCP</artifactId>
        <version>5.0.1</version>
    </dependency>
    <dependency>
        <groupId>org.apache.commons</groupId>
        <artifactId>commons-dbcp2</artifactId>
        <version>2.10.0</version>
    </dependency>
    <dependency>
        <groupId>org.apache.tomcat</groupId>
        <artifactId>tomcat-jdbc</artifactId>
        <version>10.1.15</version>
    </dependency>
    <!-- H2内存数据库,排除真实DB的IO干扰 -->
    <dependency>
        <groupId>com.h2database</groupId>
        <artifactId>h2</artifactId>
        <version>2.2.224</version>
    </dependency>
</dependencies>

2. 基准测试代码

import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.runner.Runner;
import org.openjdk.jmh.runner.RunnerException;
import org.openjdk.jmh.runner.options.Options;
import org.openjdk.jmh.runner.options.OptionsBuilder;

import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.concurrent.TimeUnit;

@BenchmarkMode(Mode.Throughput)
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Benchmark)
@Fork(1)
@Warmup(iterations = 3, time = 5)
@Measurement(iterations = 5, time = 10)
public class ConnectionPoolBenchmark {

    private DataSource hikariDs;
    private DataSource dbcp2Ds;
    private DataSource tomcatDs;

    @Setup(Level.Trial)
    public void setup() {
        // 初始化HikariCP
        com.zaxxer.hikari.HikariConfig hikariConfig = new com.zaxxer.hikari.HikariConfig();
        hikariConfig.setJdbcUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
        hikariConfig.setUsername("sa");
        hikariConfig.setPassword("");
        hikariConfig.setMaximumPoolSize(20);
        hikariDs = new com.zaxxer.hikari.HikariDataSource(hikariConfig);

        // 初始化DBCP2
        org.apache.commons.dbcp2.BasicDataSource dbcp2Config = new org.apache.commons.dbcp2.BasicDataSource();
        dbcp2Config.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
        dbcp2Config.setUsername("sa");
        dbcp2Config.setPassword("");
        dbcp2Config.setMaxTotal(20);
        dbcp2Ds = dbcp2Config;

        // 初始化Tomcat JDBC Pool
        org.apache.tomcat.jdbc.pool.DataSource tomcatConfig = new org.apache.tomcat.jdbc.pool.DataSource();
        tomcatConfig.setUrl("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1");
        tomcatConfig.setUsername("sa");
        tomcatConfig.setPassword("");
        tomcatConfig.setMaxActive(20);
        tomcatDs = tomcatConfig;
    }

    @TearDown(Level.Trial)
    public void tearDown() throws SQLException {
        ((com.zaxxer.hikari.HikariDataSource) hikariDs).close();
        ((org.apache.commons.dbcp2.BasicDataSource) dbcp2Ds).close();
        ((org.apache.tomcat.jdbc.pool.DataSource) tomcatDs).close();
    }

    @Benchmark
    @Threads(20) // 并发线程数与连接池最大容量一致,模拟满负载场景
    public void testHikariCP() throws SQLException {
        try (Connection conn = hikariDs.getConnection()) {
            // 执行简单查询,避免连接操作被JIT优化
            conn.createStatement().execute("SELECT 1");
        }
    }

    @Benchmark
    @Threads(20)
    public void testDBCP2() throws SQLException {
        try (Connection conn = dbcp2Ds.getConnection()) {
            conn.createStatement().execute("SELECT 1");
        }
    }

    @Benchmark
    @Threads(20)
    public void testTomcatJDBC() throws SQLException {
        try (Connection conn = tomcatDs.getConnection()) {
            conn.createStatement().execute("SELECT 1");
        }
    }

    public static void main(String[] args) throws RunnerException {
        Options options = new OptionsBuilder()
                .include(ConnectionPoolBenchmark.class.getSimpleName())
                .build();
        new Runner(options).run();
    }
}

测试关键说明

  • 选择JMH而非手动循环:JMH会自动处理JIT预热、线程同步、测量误差等问题,测试结果更可靠。
  • 模拟满负载并发:设置线程数与连接池最大容量一致,此时不同连接池的调度效率差异会被放大。
  • 添加真实DB操作:单纯的连接获取/归还可能被JIT优化,加上简单查询能更贴近业务实际场景。
  • 使用内存数据库:H2内存DB避免了真实数据库的网络、磁盘IO干扰,聚焦连接池本身的性能表现。

扩展测试维度

如果需要更全面的性能分析,还可以:

  • 测试连接池耗尽场景:设置线程数远大于连接池最大容量,测量等待超时时间、拒绝请求比例。
  • 测试连接泄漏检测:模拟连接未归还的情况,观察不同连接池的泄漏告警、自动回收机制效率。
  • 测试长时间运行稳定性:让测试持续数小时,监控连接池的内存占用、连接存活状态。

内容的提问来源于stack exchange,提问作者chandrahas g

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 23:30:49