首页 > 数据库 >弹性数据库连接池探活策略调研(二)——Druid | 京东云技术团队

弹性数据库连接池探活策略调研(二)——Druid | 京东云技术团队

时间:2023-09-07 11:31:38浏览次数:40  
标签:1.1 Druid 版本 keepAlive 连接 连接池 探活

前言

上一篇文章中,我们介绍了弹性数据库连接失效的背景,并探讨了HikariCP连接池探活策略的相关内容。在本文中,我们将会继续探讨另一个线上常用的连接池——Druid,并为您介绍如何在使用Druid时实现最佳实践的弹性数据库连接池探活策略。

Druid

Druid的版本迭代更新比较快,同时探活配置的参数也比较多,这导致即使是相同的参数在不同的版本中达到的效果也可能不一样。但与探活相关的逻辑实现只存在源码里的两个函数里, 我们先列举一下跟Druid探活相关的参数,在具体看一下源码的实现对这些参数的使用。日后我们在开发中遇到配置探活不生效的情况下,可以看一下对应版本源码来判断自己的探活是否配置正确。

下面是与Druid探活相关的参数:

参数名称

说明

默认值

initialSize

初始化时建立物理连接的个数。初始化发生在显示调用init方法,或者第一次getConnection时。

0

minIdle

最小连接池数量。

0

maxActive

最大连接池数量。

8

testOnBorrow

申请连接时执行validationQuery配置的SQL检测连接是否有效,做了这个配置会降低性能。

false

testOnReturn

归还连接时执行validationQuery检测连接是否有效,做了这个配置会降低性能。

false

testWhileIdle

建议配置为true,不影响性能,并且保证安全性。在连接池中申请连接的时候检测,如果空闲时间大于timeBetweenEvictionRunsMillis,执行validationQuery检测连接是否有效。

大多数版本为True

timeBetweenEvictionRunsMillis

1) Destroy线程会检测连接的间隔时间,每隔这个值的时间就会执行一次DestroyTask。 2) testWhileIdle的判断依据,详细看testWhileIdle属性的说明。

大多数版本是1分钟

keepAlive

连接池中的minIdle数量以内的连接,空闲时间超过minEvictableIdleTimeMillis,则会执行探活操作此参数在1.0.28以上的版本才支持 详细说明参考官方文档。

false

keepAliveBetweenTimeMillis

配合keepAlive使用在低版本不支持,如果空闲时间小于timeBetweenEvictionRunsMillis但大于keepAliveBetweenTimeMillis扔执行探活操作

大多数版本是2分钟

validationQuery

用来检测连接是否有效的sql,要求是一个查询语句。

select 1

validationQueryTimeout

单位:秒,检测连接是否有效的超时时间。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法


minEvictableIdleTimeMillis

连接空闲时间大于该值时关闭空闲连接大于minIdle的连接,类似hikaricp的idleTimeout

30分钟

maxEvictableIdleTimeMillis

连接空闲时间大于该值时不管minIdle都关闭该连接,类似hikaricp的maxlifetime(低版本不支持)

7小时

Druid的探活主要有以下两个函数来实现:

  • com.alibaba.druid.pool.DruidDataSource#getConnectionDirect

getConnectionDirect是每次从连接池中取连接时会被调用的函数。我们从下面的代码中可以看出,如果testOnBorrow为true,则每次获取连接之前都会检测连接是否有效。如果testOnBorrow为false且testWhileIdle为true,则需要判断连接的空闲时间是否超过timeBetweenEvictionRunsMillis设置的值,如果超过则进行探活检测。失效的连接会被丢弃,并且会补充到连接池的minIdle数量。timeBetweenEvictionRunsMillis在大多数版本中的默认值为1分钟。只要这个值设置的时间小于十分钟,并且保证testWhileIdle开启,就能保证拿不到网关关闭的失效连接。

在不支持keepalive的低版本中,只能依靠testOnBorrow或testWhileIdle来进行探活。建议配置testWhileIdle来进行探活。在高并发的场景下,这种方式的性能消耗会更小一些。

弹性数据库连接池探活策略调研(二)——Druid | 京东云技术团队_数组

  • com.alibaba.druid.pool.DruidDataSource#shrink(boolean, boolean)

在下面的代码中我们可以看出,shrink方法是在DestroyTask线程的run方法中调用的,用于销毁连接池中的连接。如果timeBetweenEvictionRunsMillis大于0,则每隔这个时间间隔就会调用destroyTask.run(boolean, boolean)方法,即执行shrink方法。

弹性数据库连接池探活策略调研(二)——Druid | 京东云技术团队_默认值_02

弹性数据库连接池探活策略调研(二)——Druid | 京东云技术团队_连接池_03

从上面的代码中可以看出,shrink方法会使用keepAlive参数。需要注意的是,在不同版本的Druid中,keepAlive参数的支持和实现逻辑可能不同。官方建议在使用keepAlive参数时,应该使用1.1.21以上的版本。尽管官方文档中说明了空闲时间超过minEvictableIdleTimeMillis,就会执行探活操作,但是在高版本中,这个探活操作的执行时间也受到了keepAliveBetweenTimeMillis参数的影响。因此,在高版本中,如果想要正确地使用keepAlive参数,就需要了解其在具体版本中的实现逻辑。

下面代码是1.1.10和1.1.21版本中关于shrink方法的源码对比:

首先看一下1.1.10版本的源码,它首先会判断连接空闲时间是否大于minEvictableIdleTimeMillis,如果是,则接下来进行第二步的判断:是否是多于minIdle的空闲连接。如果是,就将这些连接加入到驱逐连接的数组中,以便进行后续的驱逐操作。如果不是,就再次判断连接空闲时间是否大于maxEvictableIdleTimeMillis,如果是,则将这些连接加入到驱逐连接的数组中。如果也不是,则进行最后的判断:是否开启了keepAlive配置。如果开启了,就将这些连接加入到保活连接数组中,以进行后续的探活操作。

弹性数据库连接池探活策略调研(二)——Druid | 京东云技术团队_数组_04

在1.1.21版本中,shrink方法的总体逻辑与1.1.10版本类似,但是新增了一个名为keepAliveBetweenTimeMillis的参数。这个参数决定了使用keepAlive进行探活的时间间隔,其默认值为2分钟,keepalive开启且空闲时间大于这个值会进行探活。

弹性数据库连接池探活策略调研(二)——Druid | 京东云技术团队_数组_05

另一个不同点是,在进行探活操作时,1.1.10版本仅会关闭无效的连接,但1.1.21版本则更进一步,除了关闭无效连接外,还会自动添加连接以达到minIdle的最小连接数。

弹性数据库连接池探活策略调研(二)——Druid | 京东云技术团队_默认值_06

1.1.10 1.1.21

总结,druid的探活参数在1.0.28版本之前没有定时的探活功能只能在每次拿到连接前进行检测是否有效,建议配置testWhileIdle为true在高并发情况下不会太影响性能,如果对可用性要求高的可以开启testOnBorrow,以在每次获取连接时检测连接的有效性。在高版本中可以用keepAlive参数对连接进行保活。针对线上使用Druid连接池的应用建议使用支持keepAlive的1.1.21或者更高版本。

JED配置模版:

Druid1.1.10

<propertyname="testWhileIdle"value="true"/>    
<propertyname="validationQuery"value="SELECT 1"/>    
<propertyname="timeBetweenEvictionRunsMillis"value="30000"/>    
<propertyname="minEvictableIdleTimeMillis"value="300000"/>
<propertyname="keepAlive"value=true/>

此版本支持keepAlive可以配置minEvictableIdleTimeMillis时间小于10分钟,能够高效的进行探活防止网关关闭连接。

Druid1.1.9

同1.1.10

Druid1.0.9

<propertyname="testWhileIdle"value="true"/>    
<propertyname="validationQuery"value="SELECT 1"/>    
<propertyname="timeBetweenEvictionRunsMillis"value="30000"/>    
<propertyname="minEvictableIdleTimeMillis"value="300000"/>

此版本不支持keepAlive只能在获取连接对象的时候检测,对可用性高的也可以开启testOnBorrow。

作者:京东零售 王雷鑫

来源:京东云开发者社区 转载请注明来源

标签:1.1,Druid,版本,keepAlive,连接,连接池,探活
From: https://blog.51cto.com/u_15714439/7395575

相关文章

  • C++_手写数据库连接池
    C++_手写数据库连接池关键技术点MySQL数据库编程、单例模式、queue队列容器、C++11多线程编程、线程互斥、线程同步通信和unique_lock、基于CAS的原子整形、智能指针shared_ptr、lambda表达式、生产者-消费者线程模型连接池的主要功能点单例模式:因为连接池只需要一个实例......
  • 深入理解数据库连接池及其在后端性能优化中的作用
    在后端开发中,数据库连接池是一个至关重要的概念,它在保障系统性能、资源利用以及稳定性方面起着重要作用。本篇博客将深入探讨数据库连接池的工作原理,以及在Java应用中如何合理地配置和使用连接池来优化后端性能。什么是数据库连接池?数据库连接池是一个管理数据库连接的技术,它在应用......
  • XApool连接池报空指针错误解决
    atorg.enhydra.jdbc.pool.GenericPool.getFromPool(GenericPool.java:200)atorg.enhydra.jdbc.pool.GenericPool.checkOut(GenericPool.java:351)atorg.enhydra.jdbc.pool.StandardPoolDataSource.getConnection(StandardPoolDataSource.java:194)atorg.enhydra.jdb......
  • SpringBoot内嵌Tomcat连接池分析
    目录1Tomcat连接池1.1简介1.2架构图1.2.1JDK线程池架构图1.2.2Tomcat线程架构1.3核心参数1.3.1AcceptCount1.3.2MaxConnections1.3.3MinSpareThread/MaxThread1.3.4MaxKeepAliveRequests1.3.5ConnectionTimeout1.3.6KeepAliveTimeout1.4核心内部线程1.4.1Acceptor1.......
  • gRPC 客户端调用服务端需要连接池吗?
    发现的问题在微服务开发中,gRPC的应用绝对少不了,一般情况下,内部微服务交互,通常是使用RPC进行通信,如果是外部通信的话,会提供https接口文档对于gRPC的基本使用可以查看文章gRPC介绍对于gRPC,我们需要基本知道如下的一些知识点:gRPC的基本四种模式的应用场景请求响应......
  • C3P0连接池配置
    C3P0是一个开放源代码的JDBC连接池,它在lib目录中与Hibernate一起发布,包括了实现jdbc3和jdbc2扩展规范说明的Connection和Statement池的DataSources对象。<c3p0-config><default-config><!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default:3--><propert......
  • 深入研究高性能数据库连接池的实现原理与优化策略
    在现代的后端应用开发中,数据库连接池是提高性能和可伸缩性的关键组件之一。本文将深入探讨数据库连接池的实现原理,涵盖Java和Python示例,并介绍一些常见的连接池优化策略。数据库连接池的作用数据库连接池是一种维护和管理数据库连接的技术,它通过预先创建一组数据库连接,并将这些连接......
  • 解密数据库连接池的奥秘与优化策略
    在后端开发中,数据库是应用程序的核心数据存储和管理部分。为了高效地处理数据库连接,提升应用性能,数据库连接池成为了不可或缺的技术。本文将深入探讨数据库连接池的工作原理,并介绍一些优化策略,帮助你更好地理解和使用数据库连接池。数据库连接池的背景与作用数据库连接是有代价的资......
  • 数据库连接池为什么要用threadlocal呢?不用会怎样?
    数据库连接池使用ThreadLocal的主要原因是为了保证每个线程都有其独立的数据库连接,这样可以避免多个线程之间的连接干扰,提高系统的稳定性和性能。为什么使用ThreadLocal?线程安全:ThreadLocal可以为每个线程提供一个独立的数据库连接,确保多个线程操作数据库时不会出现资源竞争的......
  • 根据druid将慢sql通过钉钉的方式进行告警功能记录
          想要借助接入的druid把日志里面输入的慢sql通过钉钉的方式进行告警,由于项目里面之前接入了druid,格式大概如下:    这个是接入druid并且配置了slowsql为true的情况下,日志里面打印的slowsql。刚开始我的想法是通过重写log4j的日志来进行记录,然后看了dr......