分布式 | 关于 druid 连接池参数问题

作者:鲍凤其

爱可生 dble 团队开发成员,主要负责 dble 需求开发,故障排查和社区问题解答。少说废话,放码过来。

本文来源:原创投稿

*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

最近用户在使用 druid 连接池连接 dble 时,应用会有不定时出现下面的错误:

language    java
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 425,724 milliseconds ago.  The last packet sent successfully to the server was 425,725 milliseconds ago.

这种错误还是很常见的,猜测是应用拿到了已经 close 的连接并继续使用从而引发上面的问题。因此,我们想开启 druid 中的对空闲连接检测的机制。

在查询文档的过程中,发现了两个参数,分别是 testWhileIdle 和 keepAlive(1.0.28 版本引入),那到底这两个参数有什么区别?

下面我们使用 1.1.13 版本的 druid 做一个测试。

结论

  • 开启 testWhileIdle 之后,druid 不会在 timeBetweenEvictionRunsMillis 指定的周期内检测空闲连接的有效性,而是在连接取出时对连接做一下检测。
  • 开启 keepAlive 之后,druid 会在 timeBetweenEvictionRunsMillis 指定的周期内检测空闲连接的有效性。

因此在实际使用中,建议开启 keepAlive 参数用于对空闲连接做有效性检测。Druid 中 testWhileIdle 和普通的连接池(DBCP 等)所表达的含义并不相同,使用时候需要慎重。

详细测试过程

测试程序原理是:首先初始化 druid 连接池,使其中有一个空闲连接。我们设置 TimeBetweenEvictionRunsMillis 为 10s,分别打印 10s 前后连接池中连接的信息。连接信息中 LastActiveTime 这个属性表示这条连接上次被使用的时间。通过观察前后两次打印的 LastActiveTime 是否有差别,来推断期间是否有对连接下发语句进行过有效性检测。

测试程序:

public static void main(String[] args) {
  try {
    DruidDataSource dataSource = new DruidDataSource();
 
    dataSource.setUrl("jdbc:mysql://127.0.0.1:8066/testdb2?useSSL=false&serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8");
    dataSource.setUsername("root");
    dataSource.setPassword("123456");
 
    // 开启 testWhileIdle 参数
    // dataSource.setTestWhileIdle(true);
    // 开启 keepalive 参数
    dataSource.setKeepAlive(true);
 
    // 设置检测时间为 10s
    dataSource.setTimeBetweenEvictionRunsMillis(10 * 1000);
    dataSource.setMinEvictableIdleTimeMillis(5000);
    dataSource.setValidationQuery("select 'x'");
    dataSource.setMinIdle(1);
    dataSource.setMaxActive(1);
 
    Connection conn = dataSource.getConnection();
    PreparedStatement ps = conn.prepareStatement("select 1");
    ps.close();
    conn.close();
 
    // 第一次结果
    System.out.println(dataSource.dump());
    Thread.sleep(12000);
    // 第二次结果
    System.out.println(dataSource.dump());
 
 } catch (InterruptedException e) {
    e.printStackTrace();
 } catch (SQLException e) {
    e.printStackTrace();
 }
}

开启 keepalive 参数

第一次结果:

{
 CreateTime:"2021-03-23 18:46:59",
 ActiveCount:0,
 PoolingCount:1,
 CreateCount:1,
 DestroyCount:0,
 CloseCount:1,
 ConnectCount:1,
 Connections:[
  {ID:515132998, ConnectTime:"2021-03-23 18:46:59", UseCount:1, LastActiveTime:"2021-03-23 18:47:00"}
 ]
}

第二次结果:

{
 CreateTime:"2021-03-23 18:46:59",
 ActiveCount:0,
 PoolingCount:1,
 CreateCount:1,
 DestroyCount:0,
 CloseCount:1,
 ConnectCount:1,
 Connections:[
  {ID:515132998, ConnectTime:"2021-03-23 18:46:59", UseCount:1, LastActiveTime:"2021-03-23 18:47:09"}
 ]
}

观察第一次结果和第二次结果中 Connections 的 LastActiveTime 值,分别是 2021-03-23 18:47:00 和 2021-03-23 18:47:09,发现两个值变化,可以推断出 10s 內有对连接下发语句进行过有效性检测。

开启 testWhileIdle 参数

第一次结果:

{
 CreateTime:"2021-03-23 18:52:38",
 ActiveCount:0,
 PoolingCount:1,
 CreateCount:1,
 DestroyCount:0,
 CloseCount:1,
 ConnectCount:1,
 Connections:[
  {ID:515132998, ConnectTime:"2021-03-23 18:52:39", UseCount:1, LastActiveTime:"2021-03-23 18:52:39"}
 ]
}

第二次结果:

{
 CreateTime:"2021-03-23 18:52:38",
 ActiveCount:0,
 PoolingCount:1,
 CreateCount:1,
 DestroyCount:0,
 CloseCount:1,
 ConnectCount:1,
 Connections:[
  {ID:515132998, ConnectTime:"2021-03-23 18:52:39", UseCount:1, LastActiveTime:"2021-03-23 18:52:39"}
 ]
}

观察第一次结果和第二次结果中 Connections 的 LastActiveTime 值,分别是 2021-03-23 18:52:39 和 2021-03-23 18:52:39,发现两个值没有变化,可以推断出 10s 內没有对连接下发语句进行过有效性检测。


MySQL分布式中间件DBLE
DBLE是一个基于MySQL的高可扩展性的分布式中间件,适用于高并发及TB级海量数据处理场景。

中国领先的企业数据处理技术整体解决方案提供商,开源数据库领域优秀企业。为大型行业用户的特定场景提...

355 声望
178 粉丝
0 条评论
推荐阅读
OB运维 | tenant--删除租户的流程设计
作者:姚嵩不知道是地球人还是外星人,知道的可以留言告诉小编...本文来源:原创投稿*爱可生开源社区出品,原创内容未经授权不得随意使用,转载请联系小编并注明来源。

爱可生云数据库阅读 166

谈JVM xmx, xms等内存相关参数合理性设置
说到JVM垃圾回收算法的两个优化标的:吞吐量和停顿时长,并提到这两个优化目标是有冲突的。那么有没有可能提高吞吐量而不影响停顿时长,甚至缩短停顿时长呢?答案是有可能的,提高内存占用(Memory Footprint)就...

京东云开发者1阅读 326

封面图
数据库连接池-Druid数据库连接池源码解析
本文将对Druid数据库连接池的源码进行分析和学习,以了解Druid数据库连接池的工作原理。Druid数据库连接池的基本逻辑几乎全部在DruidDataSource类中,所以本文主要是围绕DruidDataSource的各项功能展开论述。

半夏之沫阅读 1.2k

搞懂Druid之连接创建和销毁
前言Druid是阿里开源的数据库连接池,是阿里监控系统Dragoon的副产品,提供了强大的可监控性和基于Filter-Chain的可扩展性。本篇文章将对Druid数据库连接池的连接创建和销毁进行分析。分析Druid数据库连接池的源...

Java架构师1阅读 166

聊聊如何利用apollo与druid整合实现数据源动态热切
前阵子朋友部门的数据库发生宕机,导致业务无法正常操作,当时朋友他们数据库信息是配置在apollo上,朋友的想法是当数据库宕机时,可以通过切换配置在apollo上的数据库信息,实现数据源热变更。但当他们数据库发...

linyb极客之路阅读 325

为什么数据库连接池不采用 IO 多路复用?
IO多路复用被视为是非常好的性能助力器。但是一般我们在使用 DB 时,还是经常性采用c3p0,tomcat connection pool等技术来与 DB 连接,哪怕整个程序已经变成以Netty为核心。这到底是为什么?

edagarli1

中国领先的企业数据处理技术整体解决方案提供商,开源数据库领域优秀企业。为大型行业用户的特定场景提...

355 声望
178 粉丝
宣传栏