本来不打算写这个题目的,因为 Druid 大多都是在 Spring 中使用的,它很多功能非常强大,但是对于 MySQL 性能测试中并不实用。但是由于特殊原因,还是得把这个拾起来。

  在以前的性能测试的过程当中,我通常会采用 线程绑定连接 的方式进行测试,毕竟也用不到很多线程,再不济我就用 common-pool2 自己写一个。但是考虑到稳定性测试当中,持续时间非常久,自定义的功能缺少自愈能力,最终还是选择了使用已有成熟的 MySQL 连接池工具,经过几番对比,最后选择了 Druid 。

  Druid简介

  Druid连接池是阿里巴巴开源的数据库连接池项目,为监控而生,内置强大的监控功能,且监控特性不影响性能。Druid连接池功能强大,性能优越,使用占比高,是一款优秀的数据库连接池。

  Druid连接池的主要特点包括:

  Druid连接池的使用非常简单,只需几行代码即可配置和使用,是Java应用开发中不可多得的利器。

  一个例子

  

static void main(String[] args) {          // 创建 Druid 数据源          DruidDataSource dataSource = new DruidDataSource()          // 配置数据库连接信息          dataSource.setUrl("jdbc:mysql://localhost:3306/funtester")          dataSource.setUsername("root")          dataSource.setPassword("funtester")          // 获取数据库连接          Connection connection = dataSource.getConnection()          // 执行 SQL 语句          Statement statement = connection.createStatement()          def query = statement.executeQuery("select id, uid, create_time  from record order by id desc limit 10;")          while (query.next()) {              println("id: ${query.getInt(1)}, uid: ${query.getInt(2)}, create_time: ${query.getTimestamp(3)}")          }          query.close()          // 关闭数据库连接          statement.close()          connection.close()      }    

  控制台打印信息就不再展示了。

  Druid配置项

  上面例子中我们采取先创建 com.alibaba.druid.pool.DruidDataSource 对象,然后进行配置项设置。我们还有一种语法,如下:

  

// 配置Druid连接池属性      Properties properties = new Properties()      properties.put("driverClassName", "com.mysql.cj.jdbc.Driver")      properties.put("url", "jdbc:mysql://localhost:3306/funtester")      properties.put("username", "root")      properties.put("password", "funtester")      properties.put("maxActive", "2")          // 创建Druid连接池      dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties)    

  Druid连接池提供了非常丰富的配置参数,可以根据实际需求进行定制化配置,下面列出了一些常用的配置项:

  基本配置:

  初始化配置:

  超时时间配置:

  测试配置:

  空闲连接回收配置:

  其他配置:

  以上是一些Druid连接池常用的配置参数,在配置时可以根据项目实际情况进行调整。比如对于长时间保持空闲状态的应用可以将maxIdle设置小一些,而对于并发量大的应用则需要将maxActive设置大一些。配置合理的连接池参数有利于提升应用的性能和稳定性。

  并发

  在性能测试过程中少不了要对连接池并发获取连接、归还连接。下面是演示的例子:

  

import com.alibaba.druid.pool.DruidDataSource      import com.alibaba.druid.pool.DruidDataSourceFactory      import com.funtester.frame.SourceCode            import java.sql.Connection      import java.util.concurrent.CountDownLatch      import java.util.concurrent.ExecutorService      import java.util.concurrent.Executors            class DruidConcurrencyDemo extends SourceCode {                private static DruidDataSource dataSource                static {              try {                  // 配置Druid连接池属性                  Properties properties = new Properties()               properties.put(DruidDataSourceFactory.PROP_DRIVERCLASSNAME, "com.mysql.cj.jdbc.Driver")             properties.put(DruidDataSourceFactory.PROP_URL, "jdbc:mysql://localhost:3306/funtester")             properties.put(DruidDataSourceFactory.PROP_USERNAME, "root")             properties.put(DruidDataSourceFactory.PROP_PASSWORD, "funtester")             properties.put(DruidDataSourceFactory.PROP_MAXACTIVE, "10")             properties.put(DruidDataSourceFactory.PROP_INITIALSIZE, "3")             properties.put(DruidDataSourceFactory.PROP_MAXWAIT, "5000")                    // 创建Druid连接池                  dataSource = (DruidDataSource) DruidDataSourceFactory.createDataSource(properties)              } catch (Exception e) {                  e.printStackTrace()              }          }                static void main(String[] args) throws InterruptedException {              int threadCount = 4 // 模拟4个并发请求              CountDownLatch latch = new CountDownLatch(threadCount)              ExecutorService executorService = Executors.newFixedThreadPool(threadCount)                    // 并发获取连接              for (int i = 0; i  {                      try {                          Connection connection = dataSource.getConnection()                          // 模拟一些操作                          Thread.sleep(1000) // 模拟1秒的操作时间                          output("活跃连接数: " + dataSource.getActiveCount())                          output("空闲连接数: " + dataSource.getPoolingCount())                          connection.close() // 关闭连接                      } catch (Exception e) {                          e.printStackTrace()                      } finally {                          latch.countDown() // 计数器减一                      }                  })              }                    latch.await() // 等待所有线程执行完毕              executorService.shutdown() // 关闭线程池                    // 获取连接池状态              output("活跃连接数: " + dataSource.getActiveCount())              output("空闲连接数: " + dataSource.getPoolingCount())          }      }    

  控制台输出:

  

16:31:55:819 pool-2-thread-3 {dataSource-1} inited    16:31:57:353 pool-2-thread-1 活跃连接数: 2    16:31:57:353 pool-2-thread-2 活跃连接数: 2    16:31:57:354 pool-2-thread-1 空闲连接数: 0    16:31:57:354 pool-2-thread-2 空闲连接数: 0    16:31:58:365 pool-2-thread-3 活跃连接数: 2    16:31:58:365 pool-2-thread-4 活跃连接数: 2    16:31:58:365 pool-2-thread-3 空闲连接数: 0    16:31:58:366 pool-2-thread-4 空闲连接数: 0    16:31:58:369 main 活跃连接数: 0    16:31:58:370 main 空闲连接数: 2    

  如果你在设置中增加了 com.alibaba.druid.pool.DruidDataSourceFactory#PROP_MAXIDLE = "maxIdle";的话,控制台会提示:

  main maxIdle is deprecated

  该配置已经过期了。

  FunTester原创专题推荐~

最后修改:2024 年 07 月 18 日
如果觉得我的文章对你有用,请随意赞赏