Druid 连接池配置文件(线程警告问题)

  • 程序运行时的警告信息:

The web application [MiMarket] appears to have started a thread named [Druid-ConnectionPool-Destroy-485542448] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:java.lang.Thread.sleep(Native Method)

  • 我的配置文件:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db_shopping
username=root
password=

#<!--initialSize: 初始化连接-->
initialSize=10
#<!--maxIdle: 最大空闲连接,已过时-->
#maxIdle = 10
#<!--minIdle: 最小空闲连接-->
minIdle=5
#<!--maxActive: 最大连接数量-->
maxActive=50
#<!--maxWait: 超时等待时间,以毫秒为单位-->
maxWait=50000
  • 关闭服务器时的警告:

The web application [MiMarket] registered the JDBC driver [com.alibaba.druid.proxy.DruidDriver] but failed to unregister it when the web application was stopped. To prevent a memory leak, the JDBC Driver has been forcibly unregistered.

The web application [MiMarket] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread:java.lang.Object.wait(Native Method)

因为我的程序是:写法糟糕的没有关闭连接,解除注册等操作的程序。。。

 

  • 配置文件的完善写法:
driverClassName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/db_shopping
username=root
password=

#<!--initialSize: 初始化连接-->
initialSize=10
#<!--maxIdle: 最大空闲连接,已过时-->
#maxIdle = 10
#<!--minIdle: 最小空闲连接-->
minIdle=5
#<!--maxActive: 最大连接数量-->
maxActive=50
#<!--removeAbandoned: 是否自动回收超时连接-->
removeAbandoned=true
#<!--removeAbandonedTimeout: 超时时间(以秒数为单位)-->
removeAbandonedTimeout=180
#<!--maxWait: 超时等待时间,以毫秒为单位-->
maxWait=50000


validationQuery=SELECT 1
testOnBorrow=true
  • removeAbandonedTimeout  300 :

泄露的连接可以被删除的超时值,单位秒

  • removeAbandoned  false :

标记是否删除泄露的连接,如果他们超过了 removeAbandonedTimout 的限制的话。

设置为true,连接被认为是被泄露并且可以被删除,如果空闲时间超过 removeAbandonedTimeout 的话。

设置为true可以为写法糟糕的没有关闭连接的程序修复数据库连接。

如果开启"removeAbandoned",那么连接在被认为泄露时可能被池回收。

这个机制在(getNumIdle() < 2) and (getNumActive() > getMaxActive() - 3)时被触发。

  • 例:

maxActive=10, 活动连接为 8 或者空闲连接为 1 时可以触发"removeAbandoned",但这是基于活动连接没有被使用的时间超过"removeAbandonedTimeout"时,默认300秒。(在resultset中游历不被计算为被使用)

 

  • validationQuery  :

SQL查询,用来验证从连接池取出的连接,在将连接返回给调用者之前。如果指定,则查询必须是一个SQL SELECT并且必须返回至少一行记录

  • testOnBorrow  true  :

指明是否在从池中取出连接前进行检验,如果检验失败,则从池中去除连接并尝试取出另一个。

注意:设置为true后如果要生效,validationQuery参数必须设置为非空字符串

  • 例:

假如连接池中的连接被数据库关闭了,应用通过连接池getConnection时,都可能获取到这些不可用的连接,且这些连接如果不被其他线程回收的话,它们不会被连接池被废除,也不会重新被创建。

这些连接占用了连接池的名额,项目本身作为服务端,数据库链接被关闭,客户端调用服务端就会出现大量的 timeout,客户端设置了超时时间,然后主动断开,服务端必然出现 close_wait ,由于 tomcat 默认最大线程数是 200,很快就挂掉。加大tomcat 默认线程(server.tomcat.max-threads=3000)也只是短时间内其他数据源链接不会死掉。

 

以上的配置文件写法适合小项目,解决了线程的问题,我的项目运行时没有再报线程警告,但是在服务器关闭时,Abandoned 线程(连接清理线程)未关闭,以及未解除注册的警告仍旧存在,必须在程序中添加如下监听。

  • AppListener:
import com.alibaba.druid.pool.DruidDataSource;
import com.mysql.jdbc.AbandonedConnectionCleanupThread;
import utils.DruidUtils;

import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.annotation.WebListener;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Enumeration;

@WebListener()
public class AppListener implements ServletContextListener {

    // Public constructor is required by servlet spec
    public AppListener() {
    }


    @Override
    public void contextInitialized(ServletContextEvent servletContextEvent) {

    }

    @Override
    public void contextDestroyed(ServletContextEvent servletContextEvent) {
        DruidDataSource druidDataSource= (DruidDataSource) DruidUtils.getDataSource();
        druidDataSource.close();
        System.out.println("关闭连接池");
        try {
            Enumeration<Driver> drivers = DriverManager.getDrivers();
            while(drivers.hasMoreElements()){
                DriverManager.deregisterDriver(drivers.nextElement());
                System.out.println("解除注册");
            }

        } catch (SQLException e) {
            e.printStackTrace();
        }
        try {
            AbandonedConnectionCleanupThread.shutdown();
            System.out.println("关闭 Abandoned 线程");
        } catch (Exception e) {
            System.out.println("ContextFinalizer:SEVERE problem cleaning up: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

注意:com.mysql.jdbc.AbandonedConnectionCleanupThread;

这个类文件在低一些版本的 MySQL 连接的 jar 包里没有。(MySQL 5.0.8 中就没有)

                                                                                                                                                                                        

  • 7
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值