乐趣区

关于druid:分布式-关于-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 內没有对连贯下发语句进行过有效性检测。

退出移动版