Spring 引导休息服务在正常工作数小时后引发 JPA 连接错误

Spring Boot Rest Service raising JPA connection error after hours of working correctly

我在 linux ubuntu 服务器上的 Tomcat 7 容器上将 Spring Boot Rest 服务部署为 war。

其余服务仅公开一个 /detections 端点,其中 returns JSON 表示 mysql 数据库中 table 的最后 N 条记录(运行在同一台服务器上)。我的控制器通过 Spring Data JPA 访问数据库。

将服务部署到 tomcat 后,服务似乎运行良好,并且持续了几个小时。但是,如果我在第二天早上检查,该服务似乎由于 JPA 异常而崩溃(见下文)。如果我 sudo service tomcat7 restart,该服务将再次开始正常工作,而这又只会持续几个小时。

这是 logback 输出,我试图在其中分离出最相关的行

*(webapp working correctly for a number of hours)*
.
.
.
155.    2016-05-04 14:07:00,553 INFO [http-bio-8080-exec-26] o.h.t.h.SchemaUpdate [SchemaUpdate.java:218] HHH000102: Fetching database metadata
156.    2016-05-04 14:07:04,581 ERROR [http-bio-8080-exec-26] o.h.t.h.SchemaUpdate [SchemaUpdate.java:226] HHH000319: Could not get database metadata
157.    com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
.
.
381.    Caused by: java.sql.SQLException: Access denied for user 'myuser'@'localhost' (using password: YES)
.
.
.
391.    2016-05-04 14:07:04,588 ERROR [http-bio-8080-exec-26] o.h.t.h.SchemaUpdate [SchemaUpdate.java:272] HHH000299: Could not complete schema update
392.    com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Could not create connection to database server. Attempted reconnect 3 times. Giving up.
.
.
.
615.    2016-05-04 14:07:06,854 INFO [http-bio-8080-exec-26] o.s.b.a.s.AuthenticationManagerConfiguration [AuthenticationManagerConfiguration.java:170] 
616.
617.    Using default security password: 161b39f3-9d55-453f-b9e9-310244de426b
.
.
.
851.    2016-05-04 14:07:24,649 WARN [http-bio-8080-exec-26] o.h.j.i.EntityManagerFactoryRegistry [EntityManagerFactoryRegistry.java:80] HHH000436: Entity manager factory name (default) is already registered.  If entity manager will be clustered or passivated, specify a unique value for property 'hibernate.ejb.entitymanager_factory_name'
.
.
.
902.    2016-05-04 14:37:55,360 INFO [http-bio-8080-exec-28] o.s.w.s.DispatcherServlet [FrameworkServlet.java:485] FrameworkServlet 'dispatcherServlet': initialization started
903.    2016-05-04 14:37:55,377 INFO [http-bio-8080-exec-28] o.s.w.s.DispatcherServlet [FrameworkServlet.java:504] FrameworkServlet 'dispatcherServlet': initialization completed in 17 ms
904.    2016-05-04 14:37:59,849 WARN [http-bio-8080-exec-28] o.h.e.j.s.SqlExceptionHelper [SqlExceptionHelper.java:144] SQL Error: 0, SQLState: 08001
905.    2016-05-04 14:37:59,849 ERROR [http-bio-8080-exec-28] o.h.e.j.s.SqlExceptionHelper [SqlExceptionHelper.java:146] Could not create connection to database server. Attempted reconnect 3 times. Giving up.
906.    2016-05-04 14:38:00,297 ERROR [http-bio-8080-exec-28] o.s.b.c.w.ErrorPageFilter [ErrorPageFilter.java:177] Forwarding to error page from request [/detections] due to exception [Could not open JPA EntityManager for transaction; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException: Could not open connection]
907.    org.springframework.transaction.CannotCreateTransactionException: Could not open JPA EntityManager for transaction; nested exception is javax.persistence.PersistenceException: org.hibernate.exception.JDBCConnectionException: Could not open connection
.
.
.
*(similar error patterns repeat)*

这是我的 application.properties 文件(当然,mydatabase、myuser 和 mypassword 替换了实际的连接数据):

spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect
spring.datasource.driverClassName=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/mydatabase?autoReconnect=true
spring.datasource.username=myuser
spring.datasource.password=mypassoword
spring.jpa.hibernate.ddl-auto=update
spring.data.jpa.repositories.enabled=true
spring.jpa.show-sql=true

在 mysql 中,我将对 mydatabase 的所有访问权限授予用户 'myuser'@'localhost' 实际上我可以声明问题与错误的凭据无关,因为正如我提到的该服务实际上设法连接了好几个小时。在试图解决问题的第二阶段添加了 ?autoReconnect=true,但没有任何改变。

这是我的 REST 控制器的(非常简单的)代码(同样,只有相关部分)。

@RestController
@Transactional
public class DetectionController {

    @Autowired
    public DetectionRepository detectionRepository;

    .
    .
    .

    @RequestMapping(value="/detections", method=RequestMethod.GET  )
    public Object getDetectionsLimit( @RequestParam(required=false, defaultValue="0") int limit )
    {
        try {
            List<Detection> detections = detectionRepository.findTop5ByOrderByTimestampDesc(); 
            return detections;
        } catch (final Exception e ) {
            return new Object() {
                public String error = e.getMessage();
            };
        }
    }

    .
    .
    .

}

在此先感谢您的帮助

我遇到了类似的问题,添加下面提到的属性解决了我的问题,您可以试一试。

spring.datasource.test-on-borrow= true
spring.datasource.validation-query= SELECT 1