`
liangjian103
  • 浏览: 177032 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

连接池空闲导致的问题解决办法

阅读更多

这段时间由于我的项目中使用了连接池,出现了奇怪的事情,白天在公司的时候怎么测试都是正常的,但过了一个晚上就不好使了,出现如下异常:

  1. java.net.SocketException   
  2. MESSAGE: Software caused connection abort: socket write error   

在网上找了写资料才知道,原来当连接池空闲在一定时间内的时候就会断掉,解决方法是:保持时刻有链接,可以做个定时任务 隔一段时间就查一下库,以免空闲,下面这个资料很好,给大家分享一下,只需要配置几个属性就可以了:

 

我加入了这几个属性就解决了我的问题:

	
		<property name="validationQuery"><value>SELECT 1</value></property>
		<property name="testWhileIdle"><value>true</value></property>
		<property name="testOnBorrow"><value>true</value></property>

 

 

查到一些资料与大家分享,希望能够深入讨论
connection耗尽不一定就是由connection leak引起,如果你的执行队列中线程数设置的比connection pool大,而且你的某些程序占用connection时间过长,致使执行队列中的线程已经把connection pool中的所有的connection都申请出来了,此时如果再有新的执行线程响应请求申请connection,pool中已经告罄,connection就无从得到了,只有等待。这从控制台的connection监控中是看得出的。这种情况下,如果程序能正确关闭connection,connection还是会被释放的,不会泄露。

还有一种情况是已获得connection的线程间发生了死锁,没法去释放connection,使得connection被一直占用。这要去重点检查一下应用中的synchronize代码段和涉及数据库锁的代码。同时可以定时,尤其是系统挂了后作一下thread dump,重点看看运行中和等待资源的线程在忙什么和等什么。

如果要查connection leak,还是得从应用入手,仔细检查connection的分配与释放。确保connection的释放代码放在finally段中。还有就是重点检查connection有没有被一些static对象引用。泄露往往就发生在这里。JVM的GC对付一般的Connection leak还是很有效的,比如说未关闭的connection只是函数中的局部变量且并未被其它对象引用。但GC对被Static对象引用的connection是有心无力。

用profiling工具可以辅助侦测connection leak,具体做法是在CPU的代码执行视图的代码执行树里,检查get connection与close connection的执行次数是否相同?如果get connection执行次数大于close connection,这就要重点检查一下了。这一类的工具有很多,常见的有:JProfiler,JProbe,OptimizeIt
------------------------------------------------------------------------
DBCP代码研读以及就数据库连接失效的解决
问题

网上很多评论说DBCP有很多BUG,但是都没有指明是什么BUG,只有一部分人说数据库如果因为某种原因断掉后再DBCP取道的连接都是失效的连接,而没有重新取。就此研读了一下DBCP的代码,共享之。

分析

DBCP使用apache的对象池ObjectPool作为连接池的实现,有以下主要的方法

Object borrowObject() throws Exception;从对象池取得一个有效对象

void returnObject(Object obj) throws Exception;使用完的对象放回对象池

void invalidateObject(Object obj) throws Exception;使对象失效

void addObject() throws Exception;生成一个新对象


ObjectPool的一个实现就是GenericObjectPool,这个类使用对象工厂PoolableObjectFactory实现对象的生成,失效检查等等功能,以其实现数据库连接工厂PoolableConnectionFactory做以说明,主要方法:

  Object makeObject() throws Exception; 使用ConnectionFactory生成新连接

  void destroyObject(Object obj) throws Exception;关闭连接

  boolean validateObject(Object obj); 验证连接是否有效,如果_validationQuery不空,则使用该属性作为验证连接是否有效的sql语句,查询数据库

  void activateObject(Object obj) throws Exception;激活连接对象

  void passivateObject(Object obj) throws Exception; 关闭连接生成过的Statement和ResultSet,使连接处于非活动状态



而GenericObjectPool有几个主要属性

  _timeBetweenEvictionRunsMillis:失效检查线程运行时间间隔,默认-1

  _maxIdle:对象池中对象最大个数

  _minIdle:对象池中对象最小个数

  _maxActive:可以从对象池中取出的对象最大个数,为0则表示没有限制,默认为8

在构造GenericObjectPool时,会生成一个内嵌类Evictor,实现自Runnable接口。如果_timeBetweenEvictionRunsMillis大于0,每过_timeBetweenEvictionRunsMillis毫秒Evictor会调用evict()方法,检查对象的闲置时间是否大于 _minEvictableIdleTimeMillis毫秒(_minEvictableIdleTimeMillis小于等于0时则忽略,默认为30分钟),是则销毁此对象,否则就激活并校验对象,然后调用ensureMinIdle方法检查确保池中对象个数不小于_minIdle。在调用returnObject方法把对象放回对象池,首先检查该对象是否有效,然后调用PoolableObjectFactory 的passivateObject方法使对象处于非活动状态。再检查对象池中对象个数是否小于_maxIdle,是则可以把此对象放回对象池,否则销毁此对象

还有几个很重要的属性,_testOnBorrow、_testOnReturn、_testWhileIdle,这些属性的意义是取得、返回对象和空闲时是否进行验证,检查对象是否有效,默认都为false即不验证。所以当使用DBCP时,数据库连接因为某种原因断掉后,再从连接池中取得连接又不进行验证,这时取得的连接实际已经时无效的数据库连接了。网上很多说DBCP的bug应该都是如此吧,只有把这些属性设为true,再提供_validationQuery语句就可以保证数据库连接始终有效了,oracle数据库可以使用SELECT COUNT(*) FROM DUAL,不过DBCP要求_validationQuery语句查询的记录集必须不为空,可能这也可以算一个小小的BUG,其实只要_validationQuery语句执行通过就可以了。 

注意事项

所以使用DBCP连接池放必须注意构造GenericObjectPool对象时

  validationQuery:SELECT COUNT(*) FROM DUAL

  _testOnBorrow、_testOnReturn、_testWhileIdle:最好都设为true

  _minEvictableIdleTimeMillis:大于0 ,进行连接空闲时间判断,或为0,对空闲的连接不进行验证

  _timeBetweenEvictionRunsMillis:失效检查线程运行时间间隔,如果小于等于0,不会启动检查线程
------------------------------------------------------------------------
1) maxActive 连接池的最大数据库连接数。设为0表示无限制。
2) maxIdle 数据库连接的最大空闲时间。超过此空闲时间,数据库连接将被标记为不可用,然后被释放。设为0表示无限制。
3) maxWait 最大建立连接等待时间。如果超过此时间将接到异常。设为-1表示无限制。
4) removeAbandoned 回收被遗弃的(一般是忘了释放的)数据库连接到连接池中。
5) removeAbandonedTimeout 数据库连接过多长时间不用将被视为被遗弃而收回连接池中。
6) logAbandoned 将被遗弃的数据库连接的回收记入日志。
------------------------------------------------------------------------

分享到:
评论

相关推荐

    java socket连接池

    为了解决这个问题,引入了Socket连接池的概念。 连接池的工作机制如下: 1. 初始化:在服务器启动时,预先创建一定数量的Socket连接,放入池中。 2. 借用与归还:当客户端请求到来时,服务器从连接池中取出一个已...

    oracle遇到连接空闲例程

    - **定期检查连接池**:对于使用连接池的应用程序,确保定期清理和维护连接池可以有效预防连接空闲问题。 - **监控数据库性能**:利用Oracle自带的工具如AWR报告、等待事件统计等,来监控数据库性能和连接状态,及时...

    浅谈java连接池

    Java 连接池是一种优化数据库访问效率的机制,它解决了在Web应用程序中频繁建立和释放数据库连接所导致的性能问题。随着B/S架构的广泛应用,Java应用程序通过JDBC(Java Database Connectivity)与数据库进行交互。...

    数据库连接池-连接的关闭内幕

    在深入探讨数据库连接池中连接关闭的问题之前,我们首先需要了解数据库连接池的基本概念以及它在现代应用程序中的重要性。数据库连接池是一种管理多个数据库连接的方法,旨在提高应用程序性能并减少资源消耗。通过...

    手动设计自定义数据库连接池

    通过以上介绍,我们可以看到,自定义数据库连接池不仅能够解决特定的应用场景问题,还能进一步提升系统的性能表现。然而,其实现过程也相对复杂,需要开发者具备较强的编程能力和对数据库底层机制的深入理解。

    mysql连接池java源码

    阅读并理解这个纯Java实现的连接池源码,可以帮助我们深入理解数据库连接池的工作原理,为今后优化和定制自己的连接池解决方案打下坚实的基础。 总的来说,这个项目提供了一个学习和研究数据库连接池实现的绝佳...

    连接池操作Java类.rar

    3. 监控连接池状态,及时发现和解决问题,可以使用Druid等连接池提供的监控功能。 总结,连接池是Java数据库开发中的重要技术,通过合理使用连接池,可以显著提高应用程序的性能和稳定性。理解连接池的工作原理,...

    Socket连接池的简单应用

    为此,本文档介绍了一种解决这些问题的方法——Socket连接池技术,并通过具体实例来展示如何在客户端和服务端之间实现这一技术。 #### 二、Socket连接的基础概念 在深入探讨Socket连接池之前,我们需要了解两种...

    数据库的连接池

    通过监控可以查看连接池的实时状态,包括当前连接数、空闲连接数、活动连接数等,帮助开发者分析和解决问题。 总结来说,数据库连接池是提高系统性能的关键工具,通过合理配置和有效管理,可以在保证应用性能的同时...

    有关struts中的数据库连接池问题解决

    ### 有关Struts中的数据库连接池问题解决 在开发基于Web的应用程序时,尤其是在使用Struts框架这样的MVC(Model-View-Controller)架构中,数据库连接管理是至关重要的一个环节。由于数据库连接是一种关键、有限且...

    数据源和连接池

    这样既保证了连接的有效利用,也解决了长期不关闭连接可能导致的内存泄漏问题。 #### 三、常见的开源数据库连接池 1. **DBCP**: DBCP (Database Connection Pool) 是一个基于Jakarta commons-pool对象池机制的...

    IPC方式之Binder连接池

    为了解决这个问题,开发者引入了Binder连接池的概念,类似于数据库中的连接池,用于复用已经创建好的Binder对象,减少不必要的资源开销。 Binder连接池的工作原理如下: 1. 初始化连接池:预先创建一定数量的Binder...

    Delphi三层数据库连接池

    数据库连接池的工作原理是:当应用程序需要连接数据库时,它不会直接创建新的连接,而是从连接池中获取一个已经存在的、空闲的连接。如果连接池中没有可用连接,它会按照预设的策略创建新的连接并添加到池中。在操作...

    基于java的数据库连接池技术的设计与实现

    而数据库连接池则通过以下机制解决了这些问题: 1. **预创建连接**:连接池在应用程序启动时就创建了一定量的数据库连接,这些连接被存储在一个队列中。 2. **连接复用**:当应用程序需要访问数据库时,可以从连接...

    数据库连接池包(proxool.jar)

    Proxool是Apache软件基金会提供的一款开源的数据库连接池实现,它的主要功能是管理和复用数据库连接,避免了频繁创建和关闭数据库连接所导致的性能开销。在Java环境下,Proxool.jar是使用Proxool数据库连接池服务的...

Global site tag (gtag.js) - Google Analytics