【问题标题】:Getting org.springframework.transaction.CannotCreateTransactionException when sending a request after long time长时间发送请求时出现org.springframework.transaction.CannotCreateTransactionException
【发布时间】:2016-02-23 05:04:38
【问题描述】:

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

我的应用程序连接到远程 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 设置为“-1”以使其无限,但它不起作用。我不知道是否可能是关闭连接的 MySQL 服务器,如果是这种情况,我想知道当新的 http 请求到达服务器时如何让我的应用程序打开一个新的应用程序。目前我还没有启用任何类型的安全性,我的意思是我不需要任何调用我的 REST API 的客户端进行身份验证,我会在将来这样做,但现在没有必要。

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

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

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

【问题讨论】:

  • 会话超时。请参阅reference
  • 嗨,我已经看到了那个帖子,问题是无法获得超时,而我的问题是我确实获得了超时并且无法发送更多请求,除非我重新启动服务器.我想我忘了提到这一点。我会编辑帖子。

标签: java mysql spring rest spring-boot


【解决方案1】:

我已将问题缩小为 Spring-Boot 自动配置管理连接池的问题。我在阅读这篇文章后确认了我的诊断 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 服务。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-08
    • 1970-01-01
    相关资源
    最近更新 更多