Skip to content

Tomcat 的 JDBC 连接池

🏷️ Tomcat

代码示例:

java
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Statement;

import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;

public class SimplePOJOExample {

    public static void main(String[] args) throws Exception {
        PoolProperties p = new PoolProperties();
        p.setUrl("jdbc:mysql://localhost:3306/mysql");
        p.setDriverClassName("com.mysql.jdbc.Driver");
        p.setUsername("root");
        p.setPassword("password");
        p.setJmxEnabled(true);
        p.setTestWhileIdle(false);
        p.setTestOnBorrow(true);
        p.setValidationQuery("SELECT 1");
        p.setTestOnReturn(false);
        p.setValidationInterval(30000);
        p.setTimeBetweenEvictionRunsMillis(30000);
        p.setMaxActive(100);
        p.setInitialSize(10);
        p.setMaxWait(10000);
        p.setRemoveAbandonedTimeout(60);
        p.setMinEvictableIdleTimeMillis(30000);
        p.setMinIdle(10);
        p.setLogAbandoned(true);
        p.setRemoveAbandoned(true);
        p.setJdbcInterceptors(
        "org.apache.tomcat.jdbc.pool.interceptor.ConnectionState;"+
        "org.apache.tomcat.jdbc.pool.interceptor.StatementFinalizer");
        DataSource datasource = new DataSource();
        datasource.setPoolProperties(p);

        Connection con = null;
        try {
        con = datasource.getConnection();
        Statement st = con.createStatement();
        ResultSet rs = st.executeQuery("select * from user");
        int cnt = 1;
        while (rs.next()) {
            System.out.println((cnt++)+". Host:" +rs.getString("Host")+
                " User:"+rs.getString("User")+" Password:"+rs.getString("Password"));
        }
        rs.close();
        st.close();
        } finally {
        if (con!=null) try {con.close();}catch (Exception ignore) {}
        }
    }

}

pom.xml 文件添加 tomcat-jdbc 依赖

xml
<dependency>
    <groupId>org.apache.tomcat</groupId>
    <artifactId>tomcat-jdbc</artifactId>
    <version>8.5.4</version>
</dependency>

更多属性设置可参照原文:Tomcat 的 JDBC 连接池


今天发线上,出现两种错误。

  1. socket close

    发现是 Sql 查询过慢导致的,查询需要五分钟,但是 RemoveAbandonedTimeout 设置的是 60 秒。后来直接把这个值改成了 1800,之后就再没出现这个错。

  2. [连接已关闭] 或者 [...]

    线下测试一直是好的,而且开了 200 个线程同时跑也没有出现一个问题。还没调查出原因。

    怀疑是线上环境数据库结构导致的。线上采用了数据库读写分离,而且使用负载均衡搭了多台读库。

    去掉连接池之后仍然有这个错误发生,只是概率比较低。