Spring Boot webservice JDBC偶尔无法获得连接

时间:2017-12-21 18:59:04

标签: java mysql spring spring-boot jdbc

我们的Spring Boot网络应用程序存在问题,但我们无法缩小范围,也无法可靠地重现它。有时,我们的应用程序将无法获取JDBC连接,并且只会挂起15分钟。 15分钟后,将获取与数据库的连接,该过程将平稳且完整地运行(尽管它无法返回响应,因为Apache超时导致管道错误,并且在此过程完成之前很久就关闭了套接字)。此时的应用程序日志显示:

DEBUG o.s.jdbc.datasource.DataSourceUtils - Fetching JDBC Connection from DataSource

然后什么都没有,直到15分钟后应用程序恢复。 MYSQL日志在此处不显示任何内容。同时,通过这个应用程序运行的其他事务就好了,db连接成功,没问题。但这一个线程被锁定了。

我们使用spring-boot-starter-jdbc和java 1.8连接到Maria 10.0 db。 以下是与数据源设置相关的application.properties

spring.datasource.url=jdbc:mysql://ourDatabase
spring.datasource.username=AUser
spring.datasource.password=aSecretPassword
spring.datasource.driver-class-name=com.mysql.jdbc.Driver

最后,我们确实收到了一个看似相关的错误堆栈跟踪:

2017-12-21 09:36:52,913 70038378 [ajp-bio-8009-exec-1] DEBUG o.a.t.jdbc.pool.PooledConnection  - Unable to validate object:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException: Communications link failure

The last packet successfully received from the server was 3,790,114 milliseconds ago.  The last packet sent successfully to the server was 929,256 milliseconds ago.
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.mysql.jdbc.Util.handleNewInstance(Util.java:425)
at com.mysql.jdbc.SQLError.createCommunicationsException(SQLError.java:989)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3559)
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:3459)
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:3900)
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2527)
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2680)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2486)
at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2444)
at com.mysql.jdbc.StatementImpl.executeInternal(StatementImpl.java:845)
at com.mysql.jdbc.StatementImpl.execute(StatementImpl.java:745)
at org.apache.tomcat.jdbc.pool.PooledConnection.validate(PooledConnection.java:532)
at org.apache.tomcat.jdbc.pool.PooledConnection.validate(PooledConnection.java:443)
at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:802)
at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:651)
at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:198)
at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:132)

2 个答案:

答案 0 :(得分:0)

通过更改几行并向application.properties添加新行

spring.datasource.url=jdbc:mariadb://ourDatabase

spring.datasource.driver-class-name=org.mariadb.jdbc.Driver
spring.datasource.type=org.apache.tomcat.jdbc.pool.DataSource

我们产生了类似的例外,其余结果与上述相同。

2017-12-21 16:56:41,959 4475051 [ajp-bio-8009-exec-2] DEBUG o.a.t.jdbc.pool.PooledConnection  - Unable to validate object:
java.sql.SQLNonTransientConnectionException: (conn=1076254) Connection timed out (Read failed)
        at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.get(ExceptionMapper.java:175)
        at org.mariadb.jdbc.internal.util.exceptions.ExceptionMapper.getException(ExceptionMapper.java:110)
        at org.mariadb.jdbc.MariaDbStatement.executeExceptionEpilogue(MariaDbStatement.java:235)
        at org.mariadb.jdbc.MariaDbStatement.executeInternal(MariaDbStatement.java:332)
        at org.mariadb.jdbc.MariaDbStatement.execute(MariaDbStatement.java:383)
        at org.apache.tomcat.jdbc.pool.PooledConnection.validate(PooledConnection.java:532)
        at org.apache.tomcat.jdbc.pool.PooledConnection.validate(PooledConnection.java:443)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:802)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.borrowConnection(ConnectionPool.java:651)
        at org.apache.tomcat.jdbc.pool.ConnectionPool.getConnection(ConnectionPool.java:198)
        at org.apache.tomcat.jdbc.pool.DataSourceProxy.getConnection(DataSourceProxy.java:132)
        at org.springframework.jdbc.datasource.DataSourceUtils.doGetConnection(DataSourceUtils.java:111)
        at org.springframework.jdbc.datasource.DataSourceUtils.getConnection(DataSourceUtils.java:77)
        at org.springframework.jdbc.core.JdbcTemplate.execute(JdbcTemplate.java:394)
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:474)
        at org.springframework.jdbc.core.JdbcTemplate.query(JdbcTemplate.java:484)
        at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:494)
        at org.springframework.jdbc.core.JdbcTemplate.queryForObject(JdbcTemplate.java:500)

此异常介于

Fetching JDBC Connection from DataSource
之间 和

Returning JDBC Connection to DataSource

答案 1 :(得分:0)

最终,对我们有用的解决方案是在我们的Hikari Datasource中专门指定使用application.properties。一旦我们将Hikari定义为我们的数据源,而不是默认的Tomcat和mysqlDriver,问题就停止了,此后我们再也没有看到它。