首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 数据库 > 其他数据库 >

dbcp根本配置和重连配置

2012-09-03 
dbcp基本配置和重连配置最近在看一些dbcp的相关内容,顺便做一下记录,免得自己给忘记了。1. 引入dbcp (选择1

dbcp基本配置和重连配置
最近在看一些dbcp的相关内容,顺便做一下记录,免得自己给忘记了。
1. 引入dbcp (选择1.4)

??
2. dbcp的链接validate配置
    dbcp是采用了commons-pool做为其连接池管理,testOnBorrow,testOnReturn, testWhileIdle是pool是提供的几种校验机制,通过外部钩子的方式回调dbcp的相关数据库链接(validationQuery)校验dbcp相关外部钩子类:PoolableConnectionFactory,继承于common-pool PoolableObjectFactorydbcp通过GenericObjectPool这一入口,进行连接池的borrow,return处理testOnBorrow : 顾明思义,就是在进行borrowObject进行处理时,对拿到的connection进行validateObject校验testOnReturn : 顾明思义,就是在进行returnObject对返回的connection进行validateObject校验,个人觉得对数据库连接池的管理意义不大testWhileIdle : 关注的重点,GenericObjectPool中针对pool管理,起了一个Evict的TimerTask定时线程进行控制(可通过设置参数timeBetweenEvictionRunsMillis>0),定时对线程池中的链接进行validateObject校验,对无效的链接进行关闭后,会调用ensureMinIdle,适当建立链接保证最小的minIdle连接数。timeBetweenEvictionRunsMillis,设置的Evict线程的时间,单位ms,大于0才会开启evict检查线程
    validateQuery, 代表检查的sqlvalidateQueryTimeout, 代表在执行检查时,通过statement设置,statement.setQueryTimeout(validationQueryTimeout)numTestsPerEvictionRun,代表每次检查链接的数量,建议设置和maxActive一样大,这样每次可以有效检查所有的链接.
?.


?

3. dbcp的链接自动重链相关测试

相关场景:

    数据库意外重启后,原先的数据库连接池能自动废弃老的无用的链接,建立新的数据库链接网络异常中断后,原先的建立的tcp链接,应该能进行自动切换

测试需求1步骤

    建立一testCase代码配置mysql数据库循环执行在SQL查询过程异常重启mysql数据库

测试需求2步骤

    建立一testCase代码配置mysql数据库循环执行在SQL查询过程通过iptables禁用网络链接

/sbin/iptables -A INPUT -s 10.16.2.69 -j REJECT
/sbin/iptables -A FORWARD -p tcp -s 10.16.2.69 --dport 3306 -m state --state NEW,ESTABLISHED -j DROP

???? 5. iptables -F 清空规则,恢复链接通道。

?

测试需求问题记录

?

分别测试了两种配置,有validateObject的配置和没有validateObject的相关配置。

1. 没有validate配置
问题一: 异常重启mysql数据库后,居然也可以自动恢复链接,sql查询正常
跟踪了一下代码,发现这么一个问题:

    在数据库关闭的时候,client中pool通过borrowObject获取一个异常链接返回给clientclient在使用具体的异常链接进行sql调用出错了,抛了异常在finally,调用connection.close(),本意是应该调用pool通过returnObject返回到的池中,但在跟踪代码时,未见调用GenericObjectPool的returnObject继续查,发现在dbcp在中PoolingDataSource(实现DataSource接口)调用PoolableConnection(dbcp pool相关的delegate操作)进行相应关闭时,会检查_conn.isClosed(),针对DataSource如果isClosed返回为true的则不调用returnObject,直接丢弃了链接??

解释:

正因为在获取异常链接后,因为做了_conn.isClosed()判断,所以异常链接并没有返回到连接池中,所以到数据库重启恢复后,每次都是调用pool重新构造一个新的connection,所以后面就正常了_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方法,另一种就是出现一些异常也说的比较含糊。

问题二:validateObject调用时,dbcp设置的validationQueryTimeout居然没效果

看了mysql statement代码实现,找到了答案。?

mysql com.mysql.jdbc.statemen 部分代码

?

timeout时间处理:

?

?

原因总结一句话: queryTimeout的实现是通过底层数据库提供的机制,比如KILL QUERY pid. ?如果此时的网络不通,出现阻塞现象,对应的kill命令也发不出去,所以timeout设置的超时没效果。

4.最后

最后还是决定配置testWhileIdle扫描,主要考虑:

    pool池中的链接如果未被使用,可以通过testWhileIdle进行链接检查,避免在使用时后总要失败那么一次,可以及时预防配合连接池的minEvictableIdleTimeMillis(空闲链接),removeAbandoned(未释放的链接),可以更好的去避免因为一些异常情况引起的问题,防范于未然。比如使用一些分布式数据库的中间件,会有空闲链接关闭的动作,动态伸缩连接池,这时候需要能及时的发现,避免请求失败。testOnBorrow个人不太建议使用,存在性能问题,试想一下连接一般会在什么情况出问题,网络或者服务端异常终端空闲链接,网络中断你testOnBorrow检查发现不对再取一个链接还是不对,针对空闲链接处理异常关闭,可以从好业务端的重试策略进行考虑,同时配置客户端的空闲链接超时时间,maxIdle,minIdle等。

?

--------------------------------------------

新加的内容:

5.dbcp密码加密处理

以前使用jboss的jndi数据源的方式,是通过配置oracle-ds.xml,可以设置<security-domain>EncryptDBPassword</security-domain>,引用jboss login-config.xml配置的加密配置。

?

?

?

?

为了能达到同样的效果,切换为spring dbcp配置时,也有类似密码加密的功能,运行期进行密码decode,最后进行数据链接。

?

?

实现方式很简单,分析jboss的对应SecureIdentityLoginModule的实现,无非就是走了Blowfish加密算法,自己拷贝实现一份。

?

?

?

--------------------------------------------

新加的内容:

6.数据库重连机制

常见的问题:

# ...... 
#         <property name="password"><!-- 注意多了一层转化,将密码串调用decode解密为最初的数据库密码 --> 
#             <bean value="${xxxx.password.encrypted}" /> 
#             </bean> 
#         </property> 
# ........ 
# </bean>

请问一下,你的${xxxx.password.encrypted}如何在你写的类中得到,还请指教,希望说明白一点,谢谢!<p><br>这个很简单啊,可以通过spring placeholder机制。</p>
<p>?</p>
<p>定义一份config.properties</p>
<pre name="code" lazy-init="false"&gt;
       &lt;property name="locations"&gt;
            &lt;list&gt;
                &lt;value&gt;classpath*:config.properties&lt;/value&gt;
            &lt;/list&gt;
        &lt;/property&gt;
    &lt;/bean&gt;</pre>
?
<p>?</p>
<context:property-placeholder location="classpath:jdbc.properties" />

<bean id="dataSource"
value="${driverClassName}" />
<property name="url" value="${url}" />
<property name="username" value="${username}" />
<!-- 
<property name="password" value="${password}" />
-->
<property name="password">
<bean value="${xxxxx.password.encrypted}" />
</bean>
</property>
<!-- 连接池启动时的初始值 -->
<property name="initialSize" value="${initialSize}" />
<!-- 连接池的最大值 -->
<property name="maxActive" value="${maxActive}" />
<!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
<property name="maxIdle" value="${maxIdle}" />
<!--  最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
<property name="minIdle" value="${minIdle}" />
</bean>

driverClassName=com.mysql.jdbc.Driver
url=jdbc\:mysql\://localhost\:3306/ssh2
username=root
password=mysql
initialSize=1
maxActive=500
maxIdle=2
minIdle=1
xxxxx.password.encrypted=-76079f94c1e11c89

我之前是密码测试通过,加密后就通不过了,com.ssh2.util.EncryptDBPasswordFactory是按照你提供的,我做了单元测试是没有问题的,加密就测试不过了啊

楼主兄弟请问你测试通过了吗?
#             </bean>
#         </property> 

com.xxxxx.EncryptDBPasswordFactory 你这个只是一个普通的类,${xxxx.password.encrypted}得到加密的密码,根本就没有机制去解析密码的过程,你只是在里面写了两个方法而已啊#             </bean>
#         </property> 

com.xxxxx.EncryptDBPasswordFactory 你这个只是一个普通的类,${xxxx.password.encrypted}得到加密的密码,根本就没有机制去解析密码的过程,你只是在里面写了两个方法而已啊

兄弟,我帖子里只给出了具体的加解密的方法,如果你需要使用,要把剩下的代码补全。
可以通过spring的FactoryBean的方式,进行密码动态解密最后给数据库Drive进行链接建立,jboss那套也是这样

<property name= "testOnBorrow" value="false"/>
<property name= "testOnReturn" value="false"/>
<property name= "validationQuery" value="select 1"/>
<property name= "validationQueryTimeout" value="1"/>
<property name= "timeBetweenEvictionRunsMillis" value="60000"/>
<property name= "numTestsPerEvictionRun" value="${jdbc.maxActive}"/>

试了一下。发现自动重连的确挺好用,但是也是非常奇怪,为何数据库重启后,没等到扫描线程去恢复连接池,竟然新的请求直接可以访问到数据库了。

我用的数据库是 mysql,跟踪日志发现,这个时候的确是重建了一个连接,不过对于数据库重启后的首次用户访问,也只是针对这次访问新建了一个连接而已。等到扫描线程的时间间隔到了,才恢复了整个连接池。

我很不明白,当拿到的连接是无效的时候,又是怎么当场重建的。看到你的解释:“正因为在获取异常链接后,因为做了_conn.isClosed()判断,所以异常链接并没有返回到连接池中,所以到数据库重启恢复后,每次都是调用pool重新构造一个新的connection,所以后面就正常了”。但是看完这段解释,在 commons-dbcp 和 commons-pool 的源代码中也没有找到具体的实现。

如果楼主有时间,能否详细解释一下这个地方,最好能够将源码中具体是在哪里实现的说一下,非常感谢! 14 楼 jilieshi 2011-07-14   学习了
谢-谢-楼主 15 楼 wangyibao 2012-05-30   testWhileIdle只是会对idle连接进行处理吧?numTestsPerEvictionRun是否建议成和maxIdle相同的数值,并非maxActive?

热点排行