likes
comments
collection
share

vibur-dbcp 并发、快速且功能完备的 JDBC 连接池,提供先进的性能监控功能

作者站长头像
站长
· 阅读数 4

拓展阅读

从零开始手写 mybatis (三)jdbc pool 如何从零手写实现数据库连接池 dbcp?

万字长文深入浅出数据库连接池 HikariCP/Commons DBCP/Tomcat/c3p0/druid 对比

Database Connection Pool 数据库连接池概览

c3p0 数据池入门使用教程

alibaba druid 入门介绍

数据库连接池 HikariCP 性能为什么这么快?

Apache Tomcat DBCP(Database Connection Pool) 数据库连接池-01-入门介绍

vibur-dbcp 并发、快速且功能完备的 JDBC 连接池,提供先进的性能监控功能-01-入门介绍

Vibur DBCP

Vibur DBCP 是一个并发、快速且功能完备的 JDBC 连接池,提供先进的性能监控功能,包括慢 SQL 查询的检测和记录、应用线程的非饥饿保证、语句缓存以及与 Hibernate 集成等特性。

该项目主页包含了对所有 Vibur 特性和配置选项的详细描述,以及与 Hibernate 和 Spring 的各种配置示例等内容。

Vibur DBCP 基于 Vibur Object Pool 构建,后者是一个通用的并发 Java 对象池。

介绍

Vibur 是一个使用标准 Java 并发工具完全构建的 JDBC 连接池库。它具有简洁和简单的源代码基础以及模块化设计,包括一个独立的专用对象池。

在底层,它依赖于一个简单而健壮的连接池机制,该机制是在一个由信号量保护的队列之上实现的。

Vibur DBCP 使用 Java 动态代理来创建实现 JDBC API 接口的对象。这些代理是 Java 自 1.3 版本以来存在的强大工具,不依赖于任何第三方字节码操作库,如 Javassist 或 cglib。

动态代理允许 Vibur 选择需要实现的 JDBC 接口的方法。例如,Vibur DBCP 提供的主要 JDBC 接口共有约 480 个方法;然而,少于 100 个方法的调用被明确拦截和处理,所有其他方法调用都简单地转发到它们的默认实现。这大大减少了 Vibur 需要提供所有被代理的 JDBC API 接口的静态实现所需的样板代码量。

除了通常的 JDBC 连接池功能之外,Vibur DBCP 还提供了几个高级功能,可帮助识别复杂问题并回答诸如“为什么”和“在哪里”等问题,这些问题发生在具有大量运行部件的生产系统上。

主要特点一览

  • 确保没有线程会被排除在访问 JDBC 连接池连接之外。参见 poolFair 配置参数。
  • 检测和记录慢 SQL 查询、大于预期的 ResultSet 和持续时间较长的 getConnection() 方法调用。查看相关的配置属性 这里 和 这里。
  • 支持 Hibernate 3.6、4.x 和 5.x 的集成。
  • 对 JDBC Statement(Prepared 和 Callable)进行缓存支持。
  • 使用标准 Java 并发工具和动态代理构建,不使用任何 synchronized 块或方法。
  • Vibur DBCP 需要 Java 1.6+,并且仅有以下外部依赖项:其专用对象池、slf4j/log4j 和 ConcurrentLinkedHashMap。CLHM 依赖项是可选的,只有在启用/使用 JDBC Statement 缓存时,应用程序才需要提供它。

其他特点

  • 智能池大小调整 - 根据最近使用的连接数量的启发式方法,可以减少 JDBC 池中的空闲连接数量。
  • 支持验证间隔;即,在每次使用之前,从 JDBC 池获取的连接并不会被验证,只有在连接上一次使用后经过一定时间后才会进行验证。
  • 可以通过调用代理的 unwrap 方法从相应的代理对象中检索原始 JDBC 连接或 Statement 对象。
  • 为当前获取的所有 JDBC 连接提供记录(通过 JMX 或日志文件),包括它们被获取时的堆栈跟踪;如果调试丢失/未关闭的连接或者应用程序想知道当前所有连接的来源,这将非常有用。
  • JMX 支持 - 池注册了一个 MBean,通过它可以观察和/或设置各种池参数。

代码度量和性能结果

下面的源代码度量不考虑项目的测试目录,以及每个源文件顶部的 Apache 许可证注释头部分。

项目源文件数代码行数
Vibur DBCP32约 4.8K
Vibur Object Pool14约 1.2K

下面的性能结果是通过在具有 Intel i7-4702MQ 2.2GHz 处理器的机器上运行 Java 1.8.0_151,在 Ubuntu 16.04 上运行此测试而获得的。

该测试使用了 500 个线程,每个线程尝试从初始大小为 50,最大大小为 200 的池中进行 100 次获取/还原操作。

每个线程通过调用 Thread.sleep() 来模拟 2 或 5 毫秒的工作,并且池的公平参数设置如下表所示。执行时间是三次连续运行的平均值。

池公平性模拟工作时间执行时间
true2 毫秒955 毫秒
false2 毫秒1003 毫秒
true5 毫秒1714 毫秒
false5 毫秒1816 毫秒

Maven 依赖项

Vibur 工件坐标和如何从源代码构建

<dependency>
  <groupId>org.vibur</groupId>
  <artifactId>vibur-dbcp</artifactId>
  <version>25.0</version>
</dependency>

Spring with Hibernate 3.6/4.x/5.x Configuration Snippet

<!-- Vibur DBCP dataSource bean definition: -->
<bean id="dataSource" class="org.vibur.dbcp.ViburDBCPDataSource" init-method="start" destroy-method="terminate">
   <property name="jdbcUrl" value="jdbc:hsqldb:mem:sakila;shutdown=false"/>
   <property name="username" value="sa"/>
   <property name="password" value=""/>

   <property name="poolInitialSize">10</property>
   <property name="poolMaxSize">100</property>

   <property name="connectionIdleLimitInSeconds">30</property>
   <property name="testConnectionQuery">isValid</property>

   <property name="logQueryExecutionLongerThanMs" value="500"/>
   <property name="logStackTraceForLongQueryExecution" value="true"/>

   <property name="statementCacheMaxSize" value="200"/>
</bean>

<!-- For Hibernate5 set the sessionFactory class below to org.springframework.orm.hibernate5.LocalSessionFactoryBean -->
<!-- For Hibernate4 set the sessionFactory class below to org.springframework.orm.hibernate4.LocalSessionFactoryBean -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
   <property name="dataSource" ref="dataSource"/>
   <property name="packagesToScan" value="the.project.packages"/>
   <property name="hibernateProperties">
   <props>
      <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop>
      <prop key="hibernate.cache.use_second_level_cache">false</prop>
      <prop key="hibernate.cache.use_query_cache">true</prop>
   </props>
   </property>
</bean>

<!-- For Hibernate5 set the transactionManager class below to org.springframework.orm.hibernate5.HibernateTransactionManager -->
<!-- For Hibernate4 set the transactionManager class below to org.springframework.orm.hibernate4.HibernateTransactionManager -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
   <property name="sessionFactory" ref="sessionFactory"/>
</bean>

Programming Configuration Snippet

public DataSource createDataSourceWithStatementsCache() {
    ViburDBCPDataSource ds = new ViburDBCPDataSource();

    ds.setJdbcUrl("jdbc:hsqldb:mem:sakila;shutdown=false");
    ds.setUsername("sa");
    ds.setPassword("");

    ds.setPoolInitialSize(10);
    ds.setPoolMaxSize(100);

    ds.setConnectionIdleLimitInSeconds(30);
    ds.setTestConnectionQuery("isValid");

    ds.setLogQueryExecutionLongerThanMs(500);
    ds.setLogStackTraceForLongQueryExecution(true);

    ds.setStatementCacheMaxSize(200);

    ds.start();
    return ds;
}