首页 > 技术文章 > Mysql连接超时解决方案2: 配置Proxool连接池

wenjiayi 2020-05-29 23:24 原文

MySQL数据库默认的连接超时时间为8h(即wait_timeout=28800s),如果一个连接闲置时间超过8h,MySQL会主动断开这个连接。用proxool连接池可以解决Mysql自动断开重连的问题,它具有移植性好,快速、成熟、健壮等特性,同时还提供了可视化的连接池实时监控工具。proxool连接池配置如下:

1、下载相关JAR包;

从Maven Repository仓库中下载proxool相关jar包,并将proxool-0.9.1.jar和proxool-cglib.jar拷贝至项目中。

2、在WEB-INF目录下新建一个proxool.xml文件,配置如下:

<?xml version="1.0" encoding="UTF-8"?>   
<something-else-entirely>  
    <proxool>  
        <alias>dbname</alias> <!--数据源的别名-->  
        <driver-url> jdbc:mysql://localhost:3306/testdb</driver-url><!--url连接串-->  
        <driver-class>com.mysql.jdbc.Driver </driver-class> <!--驱动类-->  
        <driver-properties>  
            <property name="user" value="root" /> <!--用户名-->  
            <property name="password" value="root" /><!--密码-->  
        </driver-properties>   
        <!--最大连接数(默认5个),超过了这个连接数,再有请求时,就排在队列中等候,最大的等待请求数由maximum-new-connections决定 -->  
        <maximum-connection-count>100</maximum-connection-count>   
        <!--最小连接数(默认2个)-->  
        <minimum-connection-count>10</minimum-connection-count>   
        <!--proxool自动侦察各个连接状态的时间间隔(毫秒),侦察到空闲的连接就马上回收,超时的销毁 默认30秒-->  
        <house-keeping-sleep-time>90000</house-keeping-sleep-time>  
        <!--没有空闲连接可以分配而在队列中等候的最大请求数,超过这个请求数的用户连接就不会被接受-->  
        <maximum-new-connections>10</maximum-new-connections>
<!--如果housekeeper检测到某个线程的活动时间大于这个数值.它将会杀掉这个线程.所以确认一下你的服务器的带宽.然后定一个合适的值.默认是5分钟.-->		
<maximum-active-time>300000</maximum-active-time> 
        <!--最少保持的空闲连接数(默认2个)-->  
        <prototype-count>5</prototype-count>   
        <!--在使用之前测试-->  
        <test-before-use>true</test-before-use>  
        <!--用于保持连接的测试语句 -->  
        <house-keeping-test-sql>select sysdate from dual</house-keeping-test-sql>  
</proxool>  
<proxool>   
        <alias> dbname2</alias>   
        <driver-url>jdbc:oracle:thin:@localhost:1521:testdb2</driver-url>  
        <driver-class>oracle.jdbc.driver.OracleDriver</driver-class>   
        <driver-properties>   
            <property name="user" value="dba" />   
            <property name="password" value="dba" />   
        </driver-properties>   
        <maximum-connection-count>100</maximum-connection-count>   
        <minimum-connection-count>10</minimum-connection-count>   
<house-keeping-sleep-time>90000</house-keeping-sleep-time>   
        <maximum-new-connections>10</maximum-new-connections>   
        <maximum-active-time>300000</maximum-active-time>
<prototype-count>5</prototype-count>   
        <test-before-use>true</test-before-use>
        <house-keeping-test-sql>select sysdate from dual</house-keeping-test-sql>
    </proxool>
</something-else-entirely>

这里面你可以根据需要配置多个不同数据库的数据源。

3、配置web.xml文件;

<?xml version="1.0" encoding="UTF-8"?>  
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"  
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
    xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee   
    http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">  
<servlet>  
  <servlet-name>ServletConfigurator</servlet-name>  
  <servlet-class>org.logicalcobwebs.proxool.configuration.ServletConfigurator</servlet-class>  
  <init-param>  
    <param-name>xmlFile</param-name>  
    <param-value>WEB-INF/proxool.xml</param-value>  
  </init-param>  
  <load-on-startup>1</load-on-startup>  
</servlet> 

<!-- 1、配置proxool连接池监控 -->
<servlet>  
  <servlet-name>Admin</servlet-name>  
  <servlet-class>org.logicalcobwebs.proxool.admin.servlet.AdminServlet</servlet-class>  
</servlet>  
<servlet-mapping>  
  <servlet-name>Admin</servlet-name>  
  <url-pattern>/admin</url-pattern>  
</servlet-mapping>

<!-- 2、配置受保护域,只有Tomcat管理员才能察看连接池的信息 -->  
<security-constraint>  
  <web-resource-collection>  
      <web-resource-name>proxool</web-resource-name>   
      <url-pattern>/admin</url-pattern>  
  </web-resource-collection>  
  <auth-constraint>  
     <role-name>manager</role-name> 
  </auth-constraint>  
</security-constraint>   
<security-role>  
    <description>The role that is required to log in to the Manager Application</description>   
    <role-name>manager</role-name>   
</security-role>  
<error-page>  
    <error-code>401</error-code>  
    <location>/401.jsp</location>  
</error-page>

在应用启动后访问:http://localhost:8080/<web-name>/admin这个url即可监控。

注意:

1、配置proxool连接池监控,仅需<!-- 1、配置proxool连接池监控 -->配置;

2、配置tomcat manager查看连接池信息时,需要在401.jsp页面中添加如下配置:

<%response.setHeader("WWW-Authenticate", "Basic realm=\"Tomcat Manager Application\"");%>这句话,

否则在访问/admin察看连接池信息时,会直接跳转到401.jsp页面。

4、通过Java API配置连接池,获取连接池信息;

import java.sql.Connection; 
import java.sql.DriverManager; 
import java.sql.ResultSet; 
import java.sql.SQLException; 
import java.sql.Statement;
import org.logicalcobwebs.proxool.ProxoolException; 
import org.logicalcobwebs.proxool.ProxoolFacade; 
import org.logicalcobwebs.proxool.admin.SnapshotIF; 

public class PoolManager {
    private static int activeCount = 0; 
    public PoolManager(){   } 
    /** 
     * 获取连接 
     * getConnection 
     * @param name 
     * @return
     */
    public Connection getConnection() { 
        Connection conn = null;
        try{ 
            //proxool驱动类 
            Class.forName("org.logicalcobwebs.proxool.ProxoolDriver"); 
            //此处的dbname是在proxool.xml中配置的连接池别名,当然根据需要可以用dbname2
            conn = DriverManager.getConnection("proxool.dbname"); 
            showSnapshotInfo(); 
        }catch(Exception ex){
            ex.printStackTrace(); 
        } 
        return conn;
    }
           
    /**        
     * 此方法可以得到连接池的信息 
     * showSnapshotInfo 
     */ 
    private void showSnapshotInfo(){           
        try{           
            SnapshotIF snapshot = ProxoolFacade.getSnapshot("dbname", true); 
	    //获得活动连接数
            int curActiveCount=snapshot.getActiveConnectionCount(); 
            //获得可得到的连接数
            int availableCount=snapshot.getAvailableConnectionCount(); 
            //获得总连接数
            int maxCount=snapshot.getMaximumConnectionCount() ; 
            //当活动连接数变化时输出的信息
            if(curActiveCount!=activeCount) {           
                System.out.println("活动连接数:"+curActiveCount+",(active)可得到的连接数:"+availableCount+",(available)总连接数:"+maxCount+"(max)"); 
                activeCount=curActiveCount; 
            } 
        }catch(ProxoolException e){ 
            e.printStackTrace(); 
        } 
    }
    
    /** 
     * 获取连接 
     * getConnection 
     * @param name 
     * @return 
     */ 
    public Connection getConnection(String name){ 
        return getConnection(); 
    }

    /** 
     * 释放连接 
     * freeConnection
     * @param conn 
     */ 
    public void freeConnection(Connection conn){
        if(conn!=null){ 
            try { 
                conn.close(); 
            } catch (SQLException e) { 
                e.printStackTrace(); 
            } 
        } 
    }
   
    /** 
     * 释放连接 
     * freeConnection 
     * @param name 
     * @param con 
     */          
    public void freeConnection (String name,Connection con){ 
        freeConnection(con); 
    } 
    
    public void getQuery() { 
        try { 
            Connection conn = getConnection(); 
            if(conn != null){ 
                Statement statement = conn.createStatement(); 
                ResultSet rs = statement.executeQuery("select * from Users"); 
                int c = rs.getMetaData().getColumnCount(); 
                while(rs.next()){ 
                    System.out.println(); 
                    for(int i=1;i<=c;i++){ 
                        System.out.print(rs.getObject(i)); 
                    } 
                } 
                rs.close(); 
            } 
            freeConnection(conn); 
        } catch (SQLException e) { 
            e.printStackTrace(); 
        } 
    }
}

 

推荐阅读