zoukankan      html  css  js  c++  java
  • 解读dbcp自动重连那些事---转载

    http://agapple.iteye.com/blog/791943

    可以后另一篇做对比:http://agapple.iteye.com/blog/772507

    同样的内容,不同的描述方式,不一样的效果.

    Hi all :

    最近在做 offerdetail 优化时,替换了数据库驱动,从 c3p0 0.9.1 -> dbcp 1.4 , 顺便研究了下 dbcp 的自动重连的一套机制,也做一下分享,大家周知一下。

    数据库链接 常见的问题:

    1. 数据库意外重启后,原先的数据库连接池能自动废弃老的无用的链接,建立新的数据库链接

    2. 网络异常中断后,原先的建立的 tcp 链接,应该能进行自动切换。比如网站演习中的交换机重启会导致网络瞬断

    3. 分布式数据库中间件,比如 cobar 会定时的将空闲链接异常关闭,客户端会出现半开的空闲链接。

    大致思考解决思路:

    1.      sql 心跳检查 ( 主动式 )

    2.      拿链接尝试一下,发现处理失败丢弃链接,探雷的请求会失败几个  ( 牺牲小我,完成大我的精神 )

    3.      设置合理的空闲链接的超时时间,避免半开链接 ( 懒模式,解决半开链接 )

    下面我们来看看,在 dbcp 中是如何实现。

    sql 心跳检查

    sql validate 配置

    <property name= "testWhileIdle" ><value> true </value></property>

    <property name= "testOnBorrow" ><value> false </value></property>

    <property name= "testOnReturn" ><value> false </value></property>

    <property name= "validationQuery" ><value>select sysdate from dual</value></property>

    <property name= "validationQueryTimeout" ><value>1</value></property>

    <property name= "timeBetweenEvictionRunsMillis" ><value>30000</value></property>

    <property name= "numTestsPerEvictionRun" ><value>16</value></property>

    参数说明

      

       dbcp 是采用了 commons-pool 做为其连接池管理, testOnBorrow,testOnReturn, testWhileIdle 是 pool 是提供的几种校验机制,通过外部钩子的方式回调 dbcp 的相关数据库链接 (validationQuery) 校验 , dbcp 相关外部钩子类: PoolableConnectionFactory, 继承于 common-pool PoolableObjectFactory , dbcp 通过GenericObjectPool 这一入口,进行连接池的 borrow,return 处理。

    具体参数描述:

       1. testOnBorrow : 顾明思义,就是在进行borrowObject进行处理时,对拿到的connection进行validateObject校验

       2. testOnReturn : 顾明思义,就是在进行returnObject对返回的connection进行validateObject校验,个人觉得对数据库连接池的管理意义不大

       3. testWhileIdle : 关注的重点,GenericObjectPool中针对pool管理,起了一个 异步Evict的TimerTask定时线程进行控制 ( 可通过设置参数 timeBetweenEvictionRunsMillis>0), 定时对线程池中的链接进行validateObject校验,对无效的链接进行关闭后,会调用ensureMinIdle,适当建立链接保证最小的minIdle连接数。

       4. timeBetweenEvictionRunsMillis, 设置的Evict线程的时间,单位ms,大于0才会开启evict检查线程

       5. validateQuery , 代表检查的sql

       6. validateQueryTimeout , 代表在执行检查时,通过statement设置,statement.setQueryTimeout(validationQueryTimeout)

       7. numTestsPerEvictionRun ,代表每次检查链接的数量,建议设置和maxActive一样大,这样每次可以有效检查所有的链接.

    Sql 心跳检查几点思考:

    1. 性能问题。

    目前网站的应用大部分的瓶颈还是在I/O这一块,大部分的I/O还是在数据库的这一层面上,每一个请求可能会调用10来次SQL查询,如果不走事务,一个请求会重复获取链接,如果每次获取链接,比如在testOnBorrow都进行validateObject,性能开销不是很能接受,可以假定一次SQL操作消毫0.5~1ms(一般走了网络请求基本就这数)

    2 .成本和收益

    网站异常数据库重启,网络异常断开的频率是非常低的,一般也就在数据库升级,演习维护时才会进行,而且一般也是选在晚上,访问量相对比较低的请求,而且一般会有人员值班关注,所以异步的validateObject是可以接受,但一个前提需要确保能保证在一个合理的时间段内,数据库能完成自动重联。

    请求探雷

    相关配置

    dbcp 自身默认支持,不需要配置

    原理描述

    common-pools 通过borrowObject , returnObject完成连接的获取和释放,正常的情况是一次请求中borrow和return是一对的,有借就有还。

    但在准备returnObject时,dbcp会做一件事,就是看看这个object是否已经是坏了的,如果坏了就直接丢了,就直接给丢弃了。

    代码层面:

    1. 在dbcp中PoolingDataSource(实现DataSource接口)调用 PoolableConnection(dbcp connnection 相关的pool delegate操作)进行相应关闭时,会检查 _conn.isClosed() ,针对DataSource如果isClosed返回为 true的则不调用returnObject,直接丢弃了链接。

    2. _conn.isClosed()是否保险,从jdk的api描述中: A connection is closed if the method close has been called on it or if certain fatal errors have occurred. 里面提供两种情况,一种就是被调用了closed方法,另一种就是出现一些异常,说的比较含糊。

    空闲链接检查

    相关配置

    <property name="minEvictableIdleTimeMillis "><value>18000000</value></property>

    <property name="removeAbandoned" ><value>true</value></property> 

    <property name="removeAbandonedTimeout "><value>180</value></property>

    参数说明

    1. minEvictableIdleTimeMillis  dbcp默认是30分,需要开启异步线程Evict,否则不生效。原理很简单,就是通过一个异步线程,每次检查connnection上一次使用的时间戳,看看是否已经超过这个timeout时间设置。

    2. removeAbandoned , removeAbandonedTimeout ,主要是用于在出现链接紧张时候,会扫描一些链接未超过removeAbandonedTimeout时间还未被释放,会主动的关闭该链接。

    适用情况

    1. 我们使用的cobar后端会有定时关闭空闲链接的操作,默认的空闲链接timeout时间为1小时,和其他oracle , mysql 各不相同,所以设置好这个空闲链接的timeout时间还是挺重要.

    2. 一般会是几种情况出现需要removeAbandoned: 

    * 代码未在finally释放connection ,  不过我们都用sqlmapClientTemplate,底层都有链接释放的过程

    * 遇到数据库死锁 。以前遇到过后端存储过程做了锁表操作,导致前台集群中连接池全都被block住,后续的业务处理因为拿不到链接所有都处理失败了。

    聊聊 c3p0 配置

    还有我们配置的c3p0所谓的自动重连的3个参数,

    <prop key="acquireRetryAttempts">30</prop>

        <prop key="acquireRetryDelay">1000</prop>

        <prop key="breakAfterAcquireFailure">false</prop>

    个人觉得就是一个误导 ,这几个配置只是在从连接池获取链接时,获取失败多尝试几次,因为我们从pool从获取链接最多只会等待固定timeout时间。

    如果要达到自动重连的效果,必须要c3p0支持请求探雷或者是sql心跳检查功能,能自动的剔除无效的链接。 

    可见c3p0官方文档描述:http://www.mchange.com/projects/c3p0/index.html#configuring_recovery

    最后:

    Dbcp 将是我们以后数据库驱动选择的趋势,最后我们如何选择如何自动重连,这个也得根据我们的应用场景而定。比如只读的web系统,后台业务系统,任务系统可能处理方式就不同。

    只读Web系统:可采取请求探雷的策略,也就失败连接池个数的请求,失败了页面刷新一次就好。

    后台业务系统:一般业务都涉及数据库的写操作,很多数据不可重入,一次处理失败后就只能靠手工干预处理。这时候得考虑是否需要使用sql心跳检查,比如testOnBorrow或者testWhileIdle.

    不同数据库的validationQuery:

    http://stackoverflow.com/questions/10684244/dbcp-validationquery-for-different-databases

    There is not only one validationQuery for all databases. On each database you have to use different validationQuery.

    After few hours of googling and testing I have collected this table:

    Database validationQuery notes

    • hsqldb - select 1 from INFORMATION_SCHEMA.SYSTEM_USERS
    • Oracle - select 1 from dual
    • DB2 - select 1 from sysibm.sysdummy1
    • mysql - select 1
    • microsoft SQL Server - select 1 (tested on SQL-Server 9.0, 10.5 [2008])
    • postgresql - select 1
    • ingres - select 1
    • derby - values 1
    • H2 - select 1
    • Firebird - select 1 from rdb$database

    I wrote about it on my blog - validation query for various databases.

    In advance there is an example of class, which return validationQuery according to JDBC driver.

    Or does anybody have better solution?

  • 相关阅读:
    Android游戏开发22:Android动画的实现J2me游戏类库用于Android开发
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第三部分,完整代码)
    使用OGR创建dxf格式矢量数据
    mysql 数据库引擎 MyISAM InnoDB 大比拼 区别
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第二部分)
    mysql 更改数据库引擎
    android sqlite SQLiteDatabase 操作大全 不看后悔!必收藏!看后精通SQLITE (第一部分)
    android 数字键盘使用
    MySQL Innodb数据库性能实践
    eclipse : Error while performing database login with the driver null
  • 原文地址:https://www.cnblogs.com/davidwang456/p/4161727.html
Copyright © 2011-2022 走看看