长时间发送请求后获取org.springframework.transaction.CannotCreateTransactionException

时间:2016-02-23 05:04:39

标签: java mysql spring rest spring-boot

我正在使用Spring-Boot开发REST API应用程序。当我启动服务器(使用嵌入式tomcat)并开始向我的API发送请求时,我得到了预期的响应。但是,假设我在发送另一个请求之前等待30分钟,那时我得到 org.springframework.transaction.CannotCreateTransactionException ,其根本原因是 java.net.SocketTimeoutException:读取超时< /强>

我的应用程序连接到远程MySQL服务器数据库。

我的 WebApplicationStarter 类外观如下:

@Configuration
@EnableAutoConfiguration
@ComponentScan("monitec")
public class WebApplicationStarter extends SpringBootServletInitializer {

    @Override
    protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {
        return application.sources(WebApplicationStarter.class);
    }

    public static void main(String[] args) throws Exception {
        ApplicationContext context = SpringApplication.run(WebApplicationStarter.class, args);
    }

    @Bean
    public SessionFactory sessionFactory(HibernateEntityManagerFactory hemf) {
        return hemf.getSessionFactory();
    }

    @Bean
    public EmbeddedServletContainerFactory servletContainerFactory() {
        TomcatEmbeddedServletContainerFactory factory = new TomcatEmbeddedServletContainerFactory();

        factory.addConnectorCustomizers(connector ->
                ((AbstractProtocol) connector.getProtocolHandler()).setConnectionTimeout(10000));

        factory.setPort(7543);//TODO: Replace this hardcoded value by a system preference
        factory.setSessionTimeout(20000);

        // configure some more properties

        return factory;
    }
}

我的 application.properties 如下:

# Thymeleaf
spring.thymeleaf.cache: false
# Data Source
spring.datasource.url=jdbc:mysql://hostname:8888/schema_name
spring.datasource.username=xxxxxxxxx
spring.datasource.password=xxxxxxxxxxx
# Hibernate
spring.jpa.database-platform=org.hibernate.dialect.MySQLDialect
spring.jpa.properties.hibernate.current_session_context_class=org.springframework.orm.hibernate4.SpringSessionContext
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE
#spring.jpa.generate-ddl=true
#spring.jpa.hibernate.ddl-auto=create

我已经研究了几个帖子,并且我们已经能够解决我的问题了。我还将sessionTimeout设置为&#34; -1&#34;使它无限但它没有用。我不知道MySQL服务器是否正在关闭连接,如果是这样的话,我想知道如何在新的http请求时打开一个新的应用程序到达服务器。目前我没有启用任何类型的安全性,我的意思是我不需要任何调用我的REST API的客户端进行身份验证,我将来会这样做,但是现在没有必要。

提前感谢您,我愿意接受您给我的任何建议和改进。如果您需要我的REST控制器代码,请告诉我,我会发布它。

PD:我正在使用POST MAN REST CLIENT来测试我的应用程序。

编辑:我总是得到读取超时异常,除非我重新启动服务器,否则我不能再向服务器发送请求。这意味着在异常之后,我从任何客户端发送的每个请求,我都会继续接收异常,并且获得预期结果的唯一方法是重新启动应用程序(嵌入式tomcat)

1 个答案:

答案 0 :(得分:0)

我已经将问题缩小到Spring-Boot autoconfig管理连接池的问题。我在阅读这篇文章后证实了我的诊断 https://aodcoding.wordpress.com/2015/05/22/handling-connection-pool-issues-in-spring-boot/

所以,我通过添加连接池属性解决了这个问题,我决定不使用我提到的文章中描述的C3P0,而是使用了如下的spring boot:

spring.datasource.max-active=50
spring.datasource.initial-size=5
spring.datasource.max-idle=10
spring.datasource.min-idle=5
spring.datasource.test-while-idle=true
spring.datasource.test-on-borrow=true
spring.datasource.validation-query=SELECT 1 FROM DUAL
spring.datasource.time-between-eviction-runs-millis=5000
spring.datasource.min-evictable-idle-time-millis=60000

据我所知,问题已经解决了。我等了很长时间并重新向我的服务发送请求,我得到了适当的回复。 对我而言,下一步是启动Spring安全配置以保护REST服务。

希望对任何有同样问题的人有所帮助。因为如果你看到异常,不是很清楚问题是由于连接池,你会尝试按照错误的方向来解决问题。