0

I have the following code that connects to a remote MYSQL server from Undertow.

    static DataSource newDataSource(String uri, String user, String password) {
        GenericObjectPool connectionPool = new GenericObjectPool();
        connectionPool.setMaxActive(256);
        connectionPool.setMaxIdle(256);
        ConnectionFactory connectionFactory = new DriverManagerConnectionFactory(
                uri, user, password);
        // This constructor modifies the connection pool, setting its connection
        // factory to this. (So despite how it may appear, all of the objects
        // declared in this method are incorporated into the returned result.)
        //
        new PoolableConnectionFactory(connectionFactory, connectionPool, null,
                null, true, true); //defaultReadOnly = true, defaultAutoCommit = true
        return new PoolingDataSource(connectionPool);
    }
}

 final DataSource mysql = dbHelper.newDataSource(
                properties.getProperty("mysql.uri"),
                properties.getProperty("mysql.user"),
                properties.getProperty("mysql.password"));

try (Connection connection = mysql.getConnection();
                    PreparedStatement statement = connection.prepareStatement(
                            "SELECT userid FROM test.table WHERE id >= "
                                    + m + " AND id <= " + n + ";",
                            ResultSet.CONCUR_READ_ONLY,
                            ResultSet.CLOSE_CURSORS_AT_COMMIT)) {
                try (ResultSet resultSet = statement.executeQuery()) {
                    while (resultSet.next()) {
                        count += 1;
                    }
                }
            }
    exchange.getResponseHeaders().put(Headers.CONTENT_TYPE, TEXT_PLAIN);
    exchange.getResponseSender().send(buildTweet(count));

After the Undertow server runs for sometime, I receive the following error:

15/04/10 10:08:00 ERROR undertow.request: Blocking request failed HttpServerExchange{ GET /q6}
com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Data source rejected establishment of connection,  message from server: "Too many connections"
    at sun.reflect.GeneratedConstructorAccessor6.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
    at com.mysql.jdbc.Util.getInstance(Util.java:384)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1013)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:987)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:973)
    at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1112)
    at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2506)
    at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2539)
    at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2321)
    at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:832)
    at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:46)
    at sun.reflect.GeneratedConstructorAccessor4.newInstance(Unknown Source)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:526)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:409)
    at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:417)
    at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:344)
    at java.sql.DriverManager.getConnection(DriverManager.java:571)
    at java.sql.DriverManager.getConnection(DriverManager.java:215)
    at org.apache.commons.dbcp.DriverManagerConnectionFactory.createConnection(DriverManagerConnectionFactory.java:75)
    at org.apache.commons.dbcp.PoolableConnectionFactory.makeObject(PoolableConnectionFactory.java:582)
    at org.apache.commons.pool.impl.GenericObjectPool.borrowObject(GenericObjectPool.java:1148)
    at org.apache.commons.dbcp.PoolingDataSource.getConnection(PoolingDataSource.java:106)
    at Project.Q6Handler.handleRequest(Q6Handler.java:39)
    at io.undertow.server.Connectors.executeRootHandler(Connectors.java:177)
    at io.undertow.server.HttpServerExchange$1.run(HttpServerExchange.java:727)
    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:745)

I would like to know how to proceed ahead with closing the connections to

  1. Mysql datasource
  2. Connection
  3. Statement

The application has frequent read requests (10000 READ requests per second) How should I proceed ahead?

I thought of using mysql.getConnection().close(); right before setting the exchange headers but need to be sure to change code on the production system.

Thanks!

AngryPanda
  • 1,261
  • 2
  • 19
  • 42
  • Close is already called before you set the headers: that is what the try-with-resources does. You might want to consider rephrasing your title and maybe your question. I find it highly suspicious that you create a new data source every time. You should only create one once; now you possibly have multiple data sources hanging around, each keeping multiple connections open. – Mark Rotteveel Apr 10 '15 at 10:42
  • I create it only once and access it statically. Just for easy visibility, I have put it in the order it is. – AngryPanda Apr 10 '15 at 10:44
  • What is the max connections of your MySQL server, maybe the 256 connections that your connection pool allows is too large given the settings on your db server. – Mark Rotteveel Apr 10 '15 at 10:46
  • @MarkRotteveel Max_Connections on MySQL is 8, which is strange. Should it be reset to 256 or higher? – AngryPanda Apr 10 '15 at 11:27
  • 8 is far too low when you instruct your connection pool to hold max 256 connections, you need at least as much as your pool (+ some others for other connections/applications). You might want to ask yourself if you really need (and want) 256 connections in your pool. I have seen highly concurrent applications that only required 1/10 of that number. – Mark Rotteveel Apr 10 '15 at 11:36

1 Answers1

0

In case someone was wondering: I reset the max_connections in MySQL server to 256 and now everything works as it was supposed it.

AngryPanda
  • 1,261
  • 2
  • 19
  • 42