前言

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

DBCP

DBCP有两个版本:1.x和2.x(也称为DBCP2)。DBCP 2基于Commons Pool 2,相比1.x版本,在性能、JMX支持和其他许多方面都有所提高。由于DBCP 2.x与DBCP 1.x不是二进制兼容,所以升级到2.x的用户应该知道Java包名称已经改变,以及Maven坐标。

首先我们先列出关于DBCP探活相关的参数:

参数名称 说明 默认值
initialSize 初始化时建立物理连接的个数。 0
minIdle 最小空闲连接:连接池中容许保持空闲状态的最小连接数量,低于这个数量将创建新的连接,如果设置为0则不创建 0
maxIdle 最大空闲连接:连接池中容许保持空闲状态的最大连接数量,超过的空闲连接将被释放,如果设置为负数表示不限制 8
maxActive/maxTotal 最大活动连接:连接池在同一时间能够分配的最大活动连接的数量,超过这个值的请求进入等待队列, 如果设置为非正数则表示不限制(1.x版本 maxActive 2.x版本maxTotal) 8
testOnBorrow 指明是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个 true
testOnReturn 指明是否在归还到池中前进行检验。 false
testWhileIdle 指明连接是否被空闲连接回收器进行检验。如果检测失败,则连接将被从池中去除.注意: 设置为true后如果要生效,validationQuery参数必须设置为非空字符串 false
timeBetweenEvictionRunsMillis 驱逐连接的线程运行的时间间隔,以毫秒为单位. 如果设置为非正数,则不运行空闲连接回收器线程 -1
validationQuery 用来检测连接是否有效的sql,要求是一个查询语句。 select 1
validationQueryTimeout 单位:秒,检测连接是否有效的超时时间。底层调用jdbc Statement对象的void setQueryTimeout(int seconds)方法
minEvictableIdleTimeMillis 连接在池中处于空闲状态的最小时间,超过这个时间会被驱逐驱逐。 30分钟
softMinEvictableIdleTimeMillis 这个参数与minEvictableIdleTimeMillis相比是这个参数受minIdle的限制,当到达这个值的时候只会驱逐大于minIdle的连接数 -1
numTestsPerEvictionRun 在每次空闲连接回收器线程运行时检查的连接数量。 3

DBCP 和与Druid 的探活配置相比,尽管它们的许多参数名字和功能相似,但在细节和默认值上存在不同之处。例如,testWhileIdle 参数在 Druid 中用于判断是否在申请连接时开启探活,且需大于 timeBetweenEvictionRunsMillis 参数值。而在 DBCP 中,该参数在驱逐连接时进行判断,若开启,则直接进行验证,类似Druid中的keepAlive参数。两个连接池中,驱逐空闲连接的时间间隔都受到 timeBetweenEvictionRunsMillis 参数的控制。此外,testOnBorrow 参数的功能相同,但默认值有所不同。

另外在DBCP在驱逐线程中也受numTestsPerEvictionRun参数影响,这个参数是指每次驱逐线程运行时驱逐连接的个数,不会一次检查池内全部的连接。此外DBCP的minEvictableIdleTimeMillis跟Druid不同超时驱逐的连接数不受minidle控制。

下图是DBCP1.4.0的驱逐连接线程的源码:org.apache.commons.pool.impl.GenericObjectPool#evict

我们可以从源码中看到驱逐的连接个数从getNumTests获取,getNumTests返回的是连接池的现有size和numTestsPerEvictionRun的最小值。驱逐过程的第一步先判断空闲时间是否超过minEvictableIdleTimeMillis,没有的话再判断softMinEvictableIdleTimeMillis是否超时和现有的连接是否大于minIdle,第三个if是判断testWhileIdle的配置为true时且上面没有回收该连接,在第四步的时候对此连接进行探活。

总结:DBCP在各个版本中对探活变动不大,一般都是在驱逐连接数时可以使用testWhileIdle来进行探活,驱逐线程运行的间隔时间是timeBetweenEvictionRunsMillis参数的值,此外numTestsPerEvictionRun参数是每次驱逐线程的个数,因此我们只要使用这两个参数设置的可以在10分钟之内对池内所有连接(最大值为maxActive/maxTotal)进行探活就能有效避免JED网关的失效连接。

总的来说,DBCP在不同版本中对探活的实现方式变化不大。通常情况下,可以通过在驱逐连接时使用testWhileIdle参数来进行连接的探活。驱逐线程的运行间隔时间受timeBetweenEvictionRunsMillis参数的控制,而numTestsPerEvictionRun参数则决定了每次驱逐线程可以处理的连接数。建议numTestsPerEvictionRun配置的值和maxActive/maxTotal一致,并配置timeBetweenEvictionRunsMillis小于10分钟能够保证对所有连接进行探活,避免拿到网关失效的连接。

此外,应用使用DBCP时,默认开启testOnBorrow参数一般可以有效避免拿到失效的连接,而Druid默认不开启testOnBorrow参数。关于是否开启testOnBorrow参数,应用可以自行评估。虽然开启testOnBorrow参数会在每次拿到连接前进行连接验证,损耗一小部分性能,但是这样能够及时销毁无效连接并重建新连接,在遇到JED网关故障重启时能够有效避免应用报错。

JED配置模版:

DBCP1.4

<propertyname="minIdle"value="5"/>
<propertyname="maxActive"value="10"/>
<propertyname="testWhileIdle"value="true"/>
<propertyname="validationQuery"value="SELECT 1"/>
<propertyname="timeBetweenEvictionRunsMillis"value="300000"/>
<propertyname="numTestsPerEvictionRun"value="10"/>

DBCP2.2.0

<propertyname="minIdle"value="5"/>
<propertyname="maxTotal"value="10"/>
<propertyname="testWhileIdle"value="true"/>
<propertyname="validationQuery"value="SELECT 1"/>
<propertyname="timeBetweenEvictionRunsMillis"value="300000"/>
<propertyname="numTestsPerEvictionRun"value="10"/>

DBCP2.1.1

同2.2.0

总结

本文以JED的网关超时报错为背景,对常见的数据库连接池进行了调研,并介绍了连接池探活相关的参数和探活逻辑。通过本文的内容,读者应该了解到不同连接池的探活内容,可以根据不同的参数设置连接池,有效避免应用拿到网关关闭的连接。本文提供了在JED数据库中的连接池配置模板,读者可以根据自己的应用需求进行调整。

作者:京东零售 王雷鑫

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

弹性数据库连接池探活策略调研(三)——DBCP的更多相关文章

  1. 转!数据库连接池概念、种类、配置(DBCP\C3P0\JndI与Tomact配置连接池)

    数据库连接池概念.种类.配置(DBCP\C3P0\JndI与Tomact配置连接池) 一.DBCP 连接:DBCP 连接池是 Apache 软件基金组织下的一个开源连接池实现. 需要的 java 包c ...

  2. 主流数据库连接池性能比较 hikari druid c3p0 dbcp jdbc

    背景 对现有的数据库连接池做调研对比,综合性能,可靠性,稳定性,扩展性等因素选出推荐出最优的数据库连接池 . NOTE: 本文所有测试均是MySQL库 测试结论 1:性能方面 hikariCP> ...

  3. 数据库连接池性能比对(hikari druid c3p0 dbcp jdbc)

    https://blog.csdn.net/qq_31125793/article/details/51241943 背景 对现有的数据库连接池做调研对比,综合性能,可靠性,稳定性,扩展性等因素选出推 ...

  4. 数据库连接池,DBUtil的模板,dbcp,c3p0

    数据库连接池,DBUtil的模板,Druid使用(重点) 一.DBUtil模板 public class DBUtilTest { public static Connection connectio ...

  5. springboot数据库连接池使用策略

    springboot官方文档介绍数据库连接池的使用策略如下: Production database connections can also be auto-configured using a p ...

  6. Java线程池的拒绝策略

    一.简介 jdk1.5 版本新增了JUC并发编程包,极大的简化了传统的多线程开发.前面文章中介绍了线程池的使用,链接地址:https://www.cnblogs.com/eric-fang/p/900 ...

  7. Druid数据库连接池就这么简单

    前言 本章节主要讲解Druid数据库连接池,为什么要学Druid数据库连接池呢?? 我的知识储备数据库连接池有两种->C3P0,DBCP,可是现在看起来并不够用阿~当时学习C3P0的时候,觉得这 ...

  8. JAVA之JDBC数据库连接池总结篇

    JDBC数据库连接池 一.JDBC数据库连接池的必要性 二.数据库连接池技术 三.多种开源的数据库连接池 3.1 C3P0数据库连接池 3.2 DBCP数据库连接池 3.3 Druid(德鲁伊)数据库 ...

  9. JDBC学习笔记(8)——数据库连接池(dbcp&C3P0)

    JDBC数据库连接池的必要性 一.在使用开发基于数据库的web程序时,传统的模式基本是按一下步骤: 1)在主程序(如servlet/beans)中建立数据库连接 2)进行sql操作 3)断开数据库连接 ...

  10. 【转】JDBC学习笔记(8)——数据库连接池(dbcp&C3P0)

    转自:http://www.cnblogs.com/ysw-go/ JDBC数据库连接池的必要性 一.在使用开发基于数据库的web程序时,传统的模式基本是按一下步骤: 1)在主程序(如servlet/ ...

随机推荐

  1. 如何编写一个健壮的 npm 包

    无脑发布 npm 比如老王我,用npm init新建一个包,改把改把,然后来个npm publish,so easy ️! Too young too naive, baby ! 请容我讲述一些发布过 ...

  2. 使用默认pypi源出现连接超时

    背景信息 安装 dataworks sdk 时报错,原因是连接默认的 pypi 仓库超时 pip install aliyun-python-sdk-dataworks-public==4.2.1 报 ...

  3. 龙芯下如何进行.net core程序开发部署

    龙芯LoongArch64已经发布了对.NETCore的支持,相关工具链也已完成,目前支持.NETCore3.1..NET6..NET7版本.本文以.NETCore3.1在loongnix-serve ...

  4. 曲线艺术编程 coding curves 第十章 螺旋曲线(SPIRALS)

    原作:Keith Peters https://www.bit-101.com/blog/2022/11/coding-curves/ 译者:池中物王二狗(sheldon) 源码:github: ht ...

  5. 【TVM模型编译】1. onnx2relay.md

    上一篇介绍了onnx模型在tvm中优化的总体流程. 在这一篇中,介绍onnx模型到relay模型的转换流程,主要涉及了以下几个方面: onnx算子到relay算子转换 relay算子实现 这一篇介绍o ...

  6. #mac安装Homebrew报错问题:curl: (7) Failed to connect to raw.githubusercontent.com port 443: Connection refused

    我们在打开https://brew.sh/index_zh-cn官网的时候都会给你下面这段代码,粘贴复制就可以安装: /bin/bash -c "$(curl -fsSL https://r ...

  7. 快速上手 vercel,手把手教你白嫖部署上线你的个人项目

    一.关于 vercel Vercel 是一个云服务平台,支持静态网站(纯静态页面,比如现在base utils 文档也是基于vercel)和动态网站的应用部署.预览和上线.如果你用过 GitHub P ...

  8. SpringBoot 拦截器 & 过滤器

    拦截器 Java里的拦截器是动态拦截Action调用的对象,它提供了一种机制可以使开发者在一个Action执行的前后执行一段代码,也可以在一个Action执行前阻止其执行,同时也提供了一种可以提取Ac ...

  9. Python 引用问题 - ImportError: attempted relative import with no known parent package

    问题描述 近日在尝试引用其他文件的代码时,遇到了错误: ImportError: attempted relative import with no known parent package. 问题大 ...

  10. Java扩展Nginx之二:编译nginx-clojure源码

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 为什么要编译nginx-clojure源码 作为< ...