Search code examples
mysqlspringcloud-foundrycleardb

connection issues with cleardb from cloudfoundry (on pivotal)


we constantly face issues with the connections to MySQL hosted by ClearDB. We have a dedicated plan which offers more then 300+ connections for our application. I know the CBR on ClearDB site automatically closes an inactive connection after 60s.

The (Spring) application runs in Tomcat and uses a ConnectionPool with the following settings:

    org.apache.tomcat.jdbc.pool.DataSource dataSource = new org.apache.tomcat.jdbc.pool.DataSource();
    dataSource.setDriverClassName("com.mysql.jdbc.Driver");
    dataSource.setUrl(serviceInfo.getJdbcUrl());
    dataSource.setUsername(serviceInfo.getUserName());
    dataSource.setPassword(serviceInfo.getPassword());
    dataSource.setInitialSize(10);
    dataSource.setMaxActive(30);
    dataSource.setMaxIdle(30);
    dataSource.setTimeBetweenEvictionRunsMillis(34000);
    dataSource.setMinEvictableIdleTimeMillis(55000);
    dataSource.setTestOnBorrow(true);
    dataSource.setTestWhileIdle(true);
    dataSource.setValidationInterval(34000);
    dataSource.setValidationQuery("SELECT 1");

The error we see in our stack is:

 2015-01-13T13:36:22.75+0100 [App/0]   OUT The last packet successfully received from the server was 90,052 milliseconds ago.  The last packet sent successfully to the server was 90,051 milliseconds ago.; nested exception is com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure
 2015-01-13T13:36:22.75+0100 [App/0]   OUT The last packet successfully received from the server was 90,052 milliseconds ago.  The last packet sent successfully to the server was 90,051 milliseconds ago.

 2015-01-13T13:36:22.75+0100 [App/0]   OUT  ... 52 common frames omitted
 2015-01-13T13:36:22.75+0100 [App/0]   OUT Caused by: java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.
 2015-01-13T13:36:22.75+0100 [App/0]   OUT  at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:2914) ~[mysql-connector-java-5.1.33.jar:5.1.33]
 2015-01-13T13:36:22.75+0100 [App/0]   OUT  at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3337) ~[mysql-connector-java-5.1.33.jar:5.1.33]
 2015-01-13T13:36:22.75+0100 [App/0]   OUT  ... 64 common frames omitted

Do you have any ideas what could be causing this or did you have similar experiences with ClearDB and maybe moved somewhere else?

unfortunate I'm out of any ideas, any help is really appreciated.


Solution

  • The error you listed looks a lot like your connection has been disconnected on the remote end (i.e. by ClearDb). 60s is a pretty short window for idle connections, so I'd suggest a few changes to your pool config.

    1.) Set initialSize and minIdle (defaults to initialSize) intentionally low. This will keep the number of idle connections low. Less idle connections means there's more of a chance the connection will be reused before the 60s window expires.

    2.) You don't need maxIdle here. It defaults to maxActive.

    3.) Set timeBetweenEvictionRunsMillis lower. This sets how often the pool will check for idle connections. The default of 5s is probably fine.

    4.) Lower minEvictableIdleTimeMillis. This is the minimum amount of time the connection will be in the pool before it can be evicted. It doesn't mean it will be evicted exactly when it's this old though. If the idle check just ran and your connection is minEvictableIdleTimeMillis - 1s old, it will have to wait for the next check to evict the connection (i.e timeBetweenEvictionRunsMillis). If you're using the default timeBetweenEvictionRunsMillis of 5s, setting this to 50s should give it plenty of time.

    5.) Set the validationInterval lower. This determines how long the pool will wait since the last successful validation before it validates the connection again. I'd go with something between 2 and 5s. It's high enough that you'll get some benefit when you're busy, and low enough that it won't cause you to miss validation on bad connections.

    6.) I'd also suggest that you enable removeAbandoned and logAbandoned, with removeAbandonedTimeout set to something like 5 or 10s (most web apps shouldn't hold the db connection for that long). This will eliminate the possibility that your web app is holding the connection in an idle state for more than 60s, then trying to use it again.