【问题标题】:HikariCP too many connectionsHikariCP 连接过多
【发布时间】:2015-02-14 19:37:21
【问题描述】:

我有一个 Java Servlet,我想将连接池与 jdbc(数据库:mysql)一起使用。

这就是我正在做的事情:

(这个类是公共的最终类DBConnector)

private static final HikariDataSource dataSource = new HikariDataSource();
private static final HikariDataSource dataSource2 = new HikariDataSource();
private static final HikariDataSource dataSource3 = new HikariDataSource();

static {
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/contentdb");
    dataSource.setUsername("root2");
    dataSource.setPassword("password");
    dataSource.setMaximumPoolSize(400);
    dataSource.setMinimumIdle(5);
    dataSource.setLeakDetectionThreshold(15000);
    dataSource.setConnectionTestQuery("SELECT 1");
    dataSource.setConnectionTimeout(1000);

    dataSource2.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource2.setJdbcUrl("jdbc:mysql://localhost:3306/userdb");
    dataSource2.setUsername("root");
    dataSource2.setPassword("password");
    dataSource2.setMaximumPoolSize(300);
    dataSource2.setMinimumIdle(5);
    dataSource2.setLeakDetectionThreshold(15000);
    dataSource2.setConnectionTestQuery("SELECT 1");
    dataSource2.setConnectionTimeout(1000);

    dataSource3.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource3.setJdbcUrl("jdbc:mysql://localhost:3306/analysedb");
    dataSource3.setUsername("root2");
    dataSource3.setPassword("password");
    dataSource3.setMaximumPoolSize(200);
    dataSource3.setMinimumIdle(5);
    dataSource3.setLeakDetectionThreshold(15000);
    dataSource3.setConnectionTestQuery("SELECT 1");
    dataSource3.setConnectionTimeout(1000);

}

private DBConnector() {
    //
}

public static Connection getConnection(int dataBase) throws SQLException {
    if (dataBase == 0) {
        return dataSource.getConnection();
    } else if (dataBase == 1) {
        return dataSource2.getConnection();
    } else {
        return dataSource3.getConnection();
    }
}

当我想调用它时:

Connection con = null;
    PreparedStatement query = null;
    ResultSet result = null;
    try {
        con = DBConnector.getConnection(0);
    }catch(SQLException ex){
    }finally{
       if (result != null) {
            try {
                result.close();
            } catch (SQLException logOrIgnore) {
            }
        }
        if (query != null) {
            try {
                query.close();
            } catch (SQLException logOrIgnore) {
            }
        }
        if (con != null) {
            try {
                con.close();
            } catch (SQLException logOrIgnore) {
            }
        }
    }

但是当我点击我的应用程序时,过了一会儿它开始挂起,我收到以下错误:

java.sql.SQLException: Timeout after 1001ms of waiting for a connection.
at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:208)
at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:108)
at main.java.db.DBConnector.getConnection(DBConnector.java:60)
at main.java.ressources.SingleItemData.getVotes(SingleItemData.java:1088)
at main.java.item.methods.GET.content.GetStreamContent.getStreamContent(GetStreamContent.java:126)
at main.java.RestService.doGet(RestService.java:254)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:728)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:953)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:408)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1023)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)
at java.lang.Thread.run(Thread.java:724)

原因:com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:通信链路故障

我将 mysql max_conncetions 设置为 1000。“SHOW PROCESSLIST”查询向我显示了很多休眠进程。这些是闲置的吗?

我真的有点卡在这里。不知道是哪个设置导致了这个问题。所以我的问题是 - 是什么导致了这个错误?我究竟做错了什么?任何帮助表示赞赏。

编辑: 设置 Mysql(本地主机):

[mysqld]

user=mysql

port=3306

socket      =/Applications/XAMPP/xamppfiles/var/mysql/mysql.sock

key_buffer=16M

max_allowed_packet=1M

table_open_cache=64

sort_buffer_size=512K

net_buffer_length=8K

read_buffer_size=256K

read_rnd_buffer_size=512K

myisam_sort_buffer_size=8M

max_connections = 1000

wait_timeout = 28800

interactive_timeout = 28800

HikariCP:HikariCP-java6-2.2.5.jar

MySQL 连接器:mysql-connector-java-5.1.25-bin.jar

【问题讨论】:

  • 是的,这是正确的。所有休眠进程都是空闲进程。做一件事,在创建任何连接之前,您需要检查连接状态是否有任何打开的连接,然后关闭它,然后重新创建它。
  • 感谢您的快速答复。好吧,不-除此之外没有其他检查。我该怎么做?;)
  • 我建议您减少代码中的超时时间。 dataSource3.setConnectionTimeout(1000);
  • 好的 - 我将按照另一个教程中的建议将其设置为 34000。我很快就会在这里写信;)
  • 不 - 抱歉,这并没有改变它。同样的错误:java.sql.SQLException: Timeout after 34001ms of waiting for a connection. at com.zaxxer.hikari.pool.HikariPool.getConnection(HikariPool.java:208) at com.zaxxer.hikari.HikariDataSource.getConnection(HikariDataSource.java:108) at main.java.db.DBConnector.getConnection(DBConnector.java:62) at main.java.item.methods.GET.content.GetCont.getContent(GetCont.java:58) at main.java.RestService.doGet(RestService.java:511)

标签: java mysql hikaricp


【解决方案1】:

几件事。首先,什么版本的 HikariCP、Java 和 MySQL 驱动程序?

第二,一个池中有 400 个连接? Way too many! 每个池中从 10 到 20 开始。您会惊讶于每秒可以处理几千个事务。

第三,这是第二个问题in the FAQ。阅读答案和链接。您需要将maxLifetime 设置为比您的 MySQL 本地超时更短(1 分钟)的值。

最后,开启 DEBUG 日志,HikariCP 没有噪音。每 30 秒,管家线程运行一次并记录池统计信息。

【讨论】:

  • 这是我现在的新价值观:dataSource2.setConnectionTimeout(34000); dataSource2.setIdleTimeout(28740000); dataSource2.setMaxLifetime(28740000);
  • 好的,它正在工作。我按照你说的调整了所有设置。我还发现了一点泄漏(我没有关闭连接 - 愚蠢......)但是一次泄漏真的那么有害吗?因为在那之前,我没有使用连接池,而且泄漏并没有那么有害。啊。当然,谢谢你:)让我开心。
  • 没有池的未关闭连接通常是无害的,尤其是在您使用自动提交的情况下。 Connection 对象将被垃圾收集,最终 DB 将关闭其连接端。 使用池,未关闭的连接将导致您的应用程序冻结,因为池具有最大大小,并且当未返回连接时,它最终将清空所有连接。因此,getConnection() 的下一个调用者将始终超时。这就是为什么几乎所有池都支持泄漏检测的原因。
猜你喜欢
  • 2016-08-13
  • 2016-02-22
  • 1970-01-01
  • 2021-08-24
  • 2019-10-27
  • 2016-01-03
  • 1970-01-01
  • 2018-12-21
  • 2017-09-16
相关资源
最近更新 更多