解决Tomcat数据连接池无法释放

近段时间,公司的检测中心报表系统(SMC)的开发人员时不时找到我,说用户老是出现无法登录的情况。前些日子因为手头上 有Jboss集群的测试工作,发现用户不能登录时,都是在Tomcat中将这个项目Reload一下就好了,不过只是治标而已,因为大概几个小时之后又会 再次出现无法登录的情况。

今天上午,开发人员小毛又找到我,要我协助将这个问题根治一下,拖太久用户难保不投诉。

简单分析了一下,每次Reload一下就能解决无法登录的情况,自然而然就想到是不是session有问题呢?于是到Tomcat的manager界面看了下,发现并没有出现session粘滞暴涨的情况。

本来可以打开jconsole看看的,正好想起了之前用过的Tomcat检测工具:probe,于是直接从其他机器上scp了一个probe.war,丢到了webapps下面自动部署。

部署完之后,打开了probe网页管理后台发现smc项目的实时 数据库 连接数很高,而且只增不减!这个系统的数据池大小设置为200,此时已经是100+了,而且一直只升不降。好吧,当数据连接数达到200时,问题肯定会再次出现的。

于是我将这个问题告诉了小毛,要他自己去修改 连接池 释放机制(这里用的是项目单独设定的参数)。他说试过了,没有用,问下我有没有办法。

我这人记性一直欠佳,也很少去记忆一些参数设置,问我么?还我也只能问BD、GG了。。。

最终在强大的搜索引擎的帮助下,找到了相关参数说明,通过参考修改后成功解决了问题!

Tomcat 连接池 无法释放的解决方法:

编辑项目的连接池配置文件:context.xml,参考下面的【 数据库 连接设置】参数说明,按照实际情况调整好各项数值,尤其是Maxidle和maxActive。并记得加上removeAbandoned=true 相关释放参数即可,我们这最终设置好的context.xml如下所示:

<Resource name="jdbc/smc"
type="javax.sql.DataSource"
username="user"
password="password"
driverClassName="oracle.jdbc.driver.OracleDriver"
maxIdle="50"
maxWait="2000"
removeAbandoned="true"
removeAbandonedTimeout="180"
validationQuery="select * from dual "
url="jdbc:oracle:thin:@192.168.7.98:1521:dw"
maxActive="200"/>
1
2
3
4
5
6
7
8
9
10
11
12
<Resource name="jdbc/smc"

type="javax.sql.DataSource"

username="user"

password="password"

driverClassName="oracle.jdbc.driver.OracleDriver"

maxIdle="50"

maxWait="2000"

removeAbandoned="true"

removeAbandonedTimeout="180"

validationQuery="select * from dual "

url="jdbc:oracle:thin:@192.168.7.98:1521:dw"

maxActive="200"/>

数据库连接设置参考:

#数据库连接设置
jdbc.driverClassName=oracle.jdbc.driver.OracleDriver
jdbcjdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:DBSERVER
jdbc.username=user
jdbc.password=pass

#<!-- 初始化连接 -->
dataSource.initialSize=10

#<!-- 最大空闲连接 -->
dataSource.maxIdle=20

#<!-- 最小空闲连接 -->
dataSource.minIdle=5

#最大连接数量
dataSource.maxActive=50

#是否在自动回收超时连接的时候打印连接的超时错误
dataSource.logAbandoned=true

#是否自动回收超时连接
dataSource.removeAbandoned=true

#超时时间(以秒数为单位)
dataSource.removeAbandonedTimeout=180

#<!-- 超时等待时间以毫秒为单位 -->
dataSource.maxWait=1000
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#数据库连接设置

jdbc.driverClassName=oracle.jdbc.driver.OracleDriver

jdbcjdbc.url=jdbc:oracle:thin:@127.0.0.1:1521:DBSERVER

jdbc.username=user

jdbc.password=pass

#<!-- 初始化连接 -->

dataSource.initialSize=10

#<!-- 最大空闲连接 -->

dataSource.maxIdle=20

#<!-- 最小空闲连接 -->

dataSource.minIdle=5

#最大连接数量

dataSource.maxActive=50

#是否在自动回收超时连接的时候打印连接的超时错误

dataSource.logAbandoned=true

#是否自动回收超时连接

dataSource.removeAbandoned=true

#超时时间(以秒数为单位)

dataSource.removeAbandonedTimeout=180

#<!-- 超时等待时间以毫秒为单位 -->

dataSource.maxWait=1000

附上作者的原文说明:

在配置DBCP连接池时,主要难以理解的主要有: removeAbandoned 、logAbandoned、removeAbandonedTimeout、maxWait这四个参数,设置了rmoveAbandoned=true 那么在getNumActive()快要到getMaxActive()的时候,系统会进行无效的Connection的回收,回收的 Connection为removeAbandonedTimeout(默认300秒)中设置的秒数后没有使用的Connection,激活回收机制好像 是getNumActive()=getMaxActive()-2。

如果开启" removeAbandoned ",那么连接在被认为泄露时可能被池回收. 这个机制在(getNumIdle() < 2) and (getNumActive() > getMaxActive() - 3)时被触发.

举例:当maxActive=20, 活动连接为18,空闲连接为1时可以触发" removeAbandoned ".但是活动连接只有在没有被使用的时间超过"removeAbandonedTimeout"时才被删除,默认300秒.在resultset中游历不被计算为被使用.

logAbandoned=true的话,将会在回收事件后,在log中打印出回收Connection的错误信息,包括在哪个地方用了Connection却忘记关闭了,在调试的时候很有用。

在这里私人建议maxWait的时间不要设得太长,maxWait如果设置太长那么客户端会等待很久才激发回收事件。

通过仁兄的资料,加深了我对连接池参数的理解,非常感谢!特附上原文地址: DBCP连接池配置参数说明及优化 ,以示尊重!

时间: 2024-10-04 16:09:19

解决Tomcat数据连接池无法释放的相关文章

数据连接池JNDI

数据库连接有很多中方式,JDBC数据库的连接方式,前边我们已经介绍过了,而开发中我们经常使用的是DataBaseConnectionPool(数据库连接池,DBCP).数据库连接池到底是什么?它比jdbc数据库连接有什么优势呢?它又怎么使用呢? 一,先看一下JDBC连接,每次用户访问数据库时,需要JDBC为我们创建数据库连接,我们使用,然后关闭.而当我们加断点测试,可以发现这个过程中创建数据库连接这个过程是比较费时间的,而不是我们在数据库中操作数据费时间.所以JDBC这种方式的效率大大折扣.而且

数据连接池——JNDI

数据库连接有很多中方式,JDBC数据库的连接方式,前边我们已经介绍过了,而开发中我们经常使用的是DataBaseConnectionPool(数据库连接池,DBCP).数据库连接池到底是什么?它比jdbc数据库连接有什么优势呢?它又怎么使用呢? 一,先看一下JDBC连接,每次用户访问数据库时,需要JDBC为我们创建数据库连接,我们使用,然后关闭.而当我们加断点测试,可以发现这个过程中创建数据库连接这个过程是比较费时间的,而不是我们在数据库中操作数据费时间.所以JDBC这种方式的效率大大折扣.而且

数据连接池的使用

相比传统的数据连接而言,每次使用Connection 连接数据库时(增删查改)每次都会调用new一个连接对象,去访问数据库,而Connection对象的每次使用,在调用close()方法时,这时候的connection 它只是处于一种关闭的状态,实际而言,他还是存在与内存当中的,这样当我们的业务需求量大大增加时,这样会很耗费我们客户端的内存资源. 而数据库连接池在初始化时将创建一定数量的数据库连接放到连接池中,这些数据库连接的数量是由最小数据库连接数制约.无论这些数据库连接是否被使用,连接池都将

关于.NET大数据量大并发量的数据连接池管理

转自:http://www.cnblogs.com/virusswb/archive/2010/01/08/1642055.html 我以前对.NET连接池的认识是错误的,原来以为在web.config中设置了连接池,每次发起的数据库连接也还是会是新的,每个sql请求就是一个连接,需要打开和关闭.因此就想设计一个连接池,然后保持固定的连接数,需要数据库连接就从连接池中取出来一个给请求用,用完毕就设置连接空闲,等待下次请求.这样看来是多余的,ADO.NET已经为我们提供这样的连接池管理,每个连接字

Netbeans 中创建数据连接池和数据源步骤

1.启动glassfish服务器, 在浏览器的地址栏中输入 http://localhost:4848 2.首先建立JDBC Connection Pools: 3.new 一个Connectio Pools 4.对General Settings属性填写: 5.填写Datasource Classname:com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource Ping属性选中,可以用来检验数据连接池是否创建成功! . 6.对Ad

记录一个简单的dbcp数据连接池

这个示例用到了ThreadLocal与dbcp,我觉得有点意思,就整理了下.使用dbcp,肯定要导入commons-dbcp.jar包.下面直接贴DBUtil代码: public class DBUtil { private static DataSource ds; //定义一个数据连接池 //threadLocal是线程的局部变量,它的实例通常是类中的 private static 字段 private static ThreadLocal<Connection> connLocal=ne

jdk 动态代理 数据连接池

package com.itheima.datasource; import java.io.PrintWriter; import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayL

c3p0 数据连接池 流行开源

注意事项:配置文件规定命名,不能更改   c3p0-config <?xml version="1.0" encoding="UTF-8"?><c3p0-config>    <default-config>        <property name="driverClass">com.mysql.jdbc.Driver</property>        <property n

Hibernate_14_数据连接池的使用

在主配置文件Hibernate.cfg.xml中设置: <!-- 设置默认的事务隔离级别: 隔离级别 对应的整数表示 READ UNCOMMITED 1 READ COMMITED 2 REPEATABLE READ 4 SERIALIZEABLE 8 --> <property name="connection.isolation">2</property> <!-- C3P0连接池设定--> <!-- 使用c3p0连接池 配置连