Tomcat JDBC连接池慢

时间:2018-09-06 08:14:08

标签: java performance tomcat jdbc connection-pooling

我有一个在Tomcat 9上运行的Web应用程序。一段时间以来,我一直在使用单个JDBC Connection对象来处理所有请求,但是我知道以后必须将其更改为连接池。好了,这一天到了,现在应用程序的运行速度大大降低了(几乎快了三倍)。快速构建和慢速构建之间的唯一区别是使用连接池,我可以始终如一地生成相同的结果。测试是在具有完全相同的配置(例如,日志记录)的完全相同的系统上进行的。

该应用程序不是数据库密集型应用程序,因此事务处理时间的差异令我感到惊讶。如果没有连接池,则事务(对Web服务进行2次调用,最多导致2次DB读取和2次DB写)需要5秒钟来处理。使用连接池,完全相同的呼叫顺序需要15秒才能完成。

获取连接的代码:

import java.sql.Connection;
import java.sql.SQLException;
import org.apache.tomcat.jdbc.pool.DataSource;
import org.apache.tomcat.jdbc.pool.PoolProperties;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class UsernamePasswordConnectionRetriever implements IConnectionRetriever {

    private static final Logger LOGGER = LoggerFactory.getLogger(UsernamePasswordConnectionRetriever.class);
    private final DataSource datasource;

    public UsernamePasswordConnectionRetriever(String driver, String url, String username, String password) {
        PoolProperties p = new PoolProperties();
        p.setUrl(url);
        p.setDriverClassName(driver);
        p.setUsername(username);
        p.setPassword(password);
        p.setJmxEnabled(false);
        p.setTestWhileIdle(false);
        p.setTestOnBorrow(false);
        p.setValidationQuery("SELECT 1");
        p.setTestOnReturn(false);
        p.setValidationInterval(90000);
        p.setTimeBetweenEvictionRunsMillis(30000);
        p.setMaxActive(200);
        p.setInitialSize(2);
        p.setMaxWait(0);
        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 = new DataSource();
        datasource.setPoolProperties(p);
    }   

    @Override
    public Connection getConnection() throws SQLException {
        LOGGER.debug("DB connection pool info: {} active, {} idle", datasource.getNumActive(), datasource.getNumIdle());
        return datasource.getConnection();
    }

}

getConnection 方法由调用方在 try-with-resources 块中调用,连接是资源,因此我知道它正在关闭。此外,我总是看到相同的日志条目“ DB连接池信息:0处于活动状态,2处于空闲状态”,以便进一步确保连接不会保持打开状态。

我尝试过这些二传手的一些变体,但仍然没有看到任何真正的改变。我还关闭了slf4j日志记录,这种差异几乎可以忽略不计。

关于如何获得更好的性能并仍然使用连接池的任何建议?

编辑我应该补充一点,此处使用的数据库是MySQL,并且该系统正在Windows Server 2016机器上进行测试。我们也在Linux上进行测试,但我发布的结果全部来自Windows测试服务器。

0 个答案:

没有答案