考虑使用较短的maxLifetime值 - Hikari连接池Spring Boot

44

在启动我的SpringBoot应用程序后,几分钟后服务器启动时会遇到异常。没有在外部使用任何HikariPool配置,Spring Boot默认使用HikariPool。以下是我在控制台上看到的错误信息:

启动SpringBoot应用程序后,服务器在几分钟后启动时发生异常。没有在外部使用任何HikariPool配置,Spring Boot默认使用HikariPool。以下是我在控制台上获取的错误信息:

2020-02-20 03:16:23 - HikariPool-4 - Failed to validate connection 
com.mysql.cj.jdbc.ConnectionImpl@4c4180c8 (No operations allowed after connection closed.). 
Possibly consider using a shorter maxLifetime value.
2020-02-20 03:16:28 - HikariPool-4 - Failed to validate connection 
com.mysql.cj.jdbc.ConnectionImpl@679c2f50 (No operations allowed after connection closed.). 
Possibly consider using a shorter maxLifetime value.
2020-02-20 03:16:33 - HikariPool-4 - Failed to validate connection 
com.mysql.cj.jdbc.ConnectionImpl@16083061 (No operations allowed after connection closed.). 
Possibly consider using a shorter maxLifetime value.
2020-02-20 03:16:38 - HikariPool-4 - Failed to validate connection 
com.mysql.cj.jdbc.ConnectionImpl@4fcaf421 (No operations allowed after connection closed.). 
Possibly consider using a shorter maxLifetime value.
2020-02-20 03:16:43 - HikariPool-4 - Failed to validate connection 
com.mysql.cj.jdbc.ConnectionImpl@33df5d54 (No operations allowed after connection closed.). 
Possibly consider using a shorter maxLifetime value.
2020-02-20 03:16:48 - HikariPool-4 - Failed to validate connection 
com.mysql.cj.jdbc.ConnectionImpl@373d288c (No operations allowed after connection closed.). 
Possibly consider using a shorter maxLifetime value.
2020-02-20 03:16:48 - SQL Error: 0, SQLState: 08003
2020-02-20 03:16:48 - HikariPool-4 - Connection is not available, request timed out after 
30156ms.
2020-02-20 03:16:48 - No operations allowed after connection closed.
2020-02-20 03:16:48 - Servlet.service() for servlet [dispatcherServlet] in context with path 
[] threw exception [Request processing failed; nested exception is 
org.springframework.dao.DataAccessResourceFailureException: Unable to acquire JDBC 
Connection; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to 
acquire JDBC Connection] with root cause

什么是“根本原因”? - yeahseol
以下是完整的异常堆栈: - Sanjog
4个回答

45
问题在于spring.datasource.hikari.maxLifetime属性的默认值(默认为30分钟,参考https://github.com/brettwooldridge/HikariCP#gear-configuration-knobs-baby)高于数据库的wait_timeout属性,在我的情况下是10分钟。
所以你有两个选择,要么将hikari.maxLifetime减少到10分钟以下,要么增加数据库的wait_timeout属性。

2
你知道我们需要设置哪个属性来对应这个值吗? - Abhishek Aggarwal
3
数据源的最大生命周期为600000毫秒(以毫秒为单位)。 - GiovanyMoreno
1
我使用wait_timeout = 300(5分钟)和max-lifetime = 600000(10分钟)进行了测试。然而,我无法获得此错误。你知道为什么吗? - Canatto Filipe
1
@CanattoFilipe 当应用程序试图使用旧的连接池(早于DB wait_timeout)与数据库进行交互时,就会出现错误,它认为该连接仍然有效。因此,我认为您应该尝试模拟这种情况。 - Vikas Tawniya
RAVI SHANKAR的答案最佳,因为它告诉我们“要解决这个问题,请执行此操作”而不是“找出如何执行此操作来解决问题”。 - Magno C
1
@Kirby:Oracle中是否也有wait_timeout?我们的应用程序出现了类似的问题,但我们正在使用Oracle11g。在哪里可以设置这个wait_timeout?此外,该应用程序部署在Weblogic中。这个错误是否与某些Weblogic设置有关? - chaatat

20

您可以在 application.properties 文件中设置以下值:

spring.datasource.hikari.maxLifeTime=600000 #10 minutes wait time

0
在我的情况下,我通过这个设置解决了问题。
@Configuration
public class HikariSetting{

    @Bean
    public HikariConfig config() {
        HikariConfig hikariConfig = new HikariConfig();
        
        // other setting
        
        hikariConfig.addDataSourceProperty("socketTimeout", 600000);
        hikariConfig.setMaxLifetime(600000);
        
        return hikariConfig;
    }
    
}

参考 this


8
不需要定义bean,只需在你的 application.properties 中提供适当的属性即可。建议通过替换bean来修复此问题并不是正确的解决方案。 - M. Deinum
@M.Deinum然而让人们了解这些bean并不会有害。我仍然觉得它很有用,但我同意最佳的配置实践是使用属性文件。 - Levent Divilioglu
7
问题在于,在定义bean时,如果没有进一步/适当的了解,在Spring Boot中自动配置的某些部分会被撤销。这经常会给没有适当知识的用户带来令人惊讶的结果。 - M. Deinum

0
当数据库连接在空闲一段时间后关闭,但连接线程在此之后尝试进行调用时,就会出现此警告。我在应用程序的yml文件中使用以下Hikari配置来保持我的连接活动。
hikari:
  connectionTestQuery: SELECT 1
  connection-timeout: 300000
  idle-timeout: 15000
  max-lifetime: 35000
  validationTimeout: 300000

在一段时间间隔后,将使用connectionTestQuery来查询数据库,并且不会让数据库连接关闭。

然后,只需像下面这样在数据库配置类中指定这些配置。

@ConfigurationProperties(prefix = "hikari")
public DataSource dataSource() {... }

注意:这只是一个警告,对您的代码没有实质性影响,除了打开一个新的连接来恢复任务。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接