为啥 spring-boot 和 postgres 连接会在一段时间后断开?

Posted

技术标签:

【中文标题】为啥 spring-boot 和 postgres 连接会在一段时间后断开?【英文标题】:why does spring-boot and postgres connection breaks after certain time?为什么 spring-boot 和 postgres 连接会在一段时间后断开? 【发布时间】:2015-12-27 21:39:21 【问题描述】:

我使用 tomcat-connection-pool 使用 gradle 运行 Spring-Boot。所有标准的 spring-boot-tools。我在那个网络服务器上运行了几个肥皂网络服务。测试服务器负载时一切正常。但是在大约 7.5 小时内无所事事之后,就会发生此异常。当然是timeout,但我尝试通过以下方式阻止它:

spring.datasource.url=jdbc:postgresql://mydb?autoReconnect=true 我将@transactional 用于某些语句。但总的来说,我只使用 spring-boot 中的JPA-Repository。 连接由 tomcat-connection-pool 管理,因此不存在空闲连接问题。 当我重新启动应用程序服务器时,一切再次正常运行。

我的数据库服务器运行PostgreSQL 9.4.1 on x86_64-unknown-linux-gnu,并且数据库和应用服务器之间没有防火墙。

我需要tcp_keep alives吗?

为什么我的连接在一段时间后断开并且无法恢复?

我的应用程序属性:

#
# [ Database Configuration Section ]
#
spring.jpa.database=POSTGRESQL
spring.jpa.show-sql=false
hibernate.format_sql=true
hibernate.hbm2ddl.auto=validate
spring.jpa.hibernate.naming-strategy=org.hibernate.cfg.DefaultNamingStrategy

spring.datasource.platform=postgres
spring.database.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://*****:5434/******
spring.datasource.username=*****
spring.datasource.password=*****

logging.file=*******.log
logging.level.=WARNING

2015-09-29 11:58:50.598  INFO 10498 --- [nio-9092-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : Initializing Spring FrameworkServlet 'dispatcherServlet'
2015-09-29 11:58:50.598  INFO 10498 --- [nio-9092-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2015-09-29 11:58:50.674  INFO 10498 --- [nio-9092-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 76 ms

2015-09-29 19:23:03.777  WARN 10498 --- [ool-3-thread-16] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: 08006
2015-09-29 19:23:03.779 ERROR 10498 --- [ool-3-thread-16] o.h.engine.jdbc.spi.SqlExceptionHelper   : An I/O error occurred while sending to the backend.
2015-09-29 19:23:03.785  INFO 10498 --- [ool-3-thread-16] o.h.e.j.b.internal.AbstractBatchImpl     : HHH000010: On release of batch it still contained JDBC statements
2015-09-29 19:23:03.836 ERROR 10498 --- [ool-3-thread-16] o.s.orm.jpa.JpaTransactionManager        : Commit exception overridden by rollback exception
java.net.SocketException: Connection timed out
    at java.net.SocketInputStream.socketRead0(Native Method) ~[na:1.8.0_25]
    at java.net.SocketInputStream.read(SocketInputStream.java:150) ~[na:1.8.0_25]
    at java.net.SocketInputStream.read(SocketInputStream.java:121) ~[na:1.8.0_25]
    at org.postgresql.core.VisibleBufferedInputStream.readMore(VisibleBufferedInputStream.java:143) ~[postgresql-9.4-1202-jdbc41.jar!/:9.4]
    at org.postgresql.core.VisibleBufferedInputStream.ensureBytes(VisibleBufferedInputStream.java:112) ~[postgresql-9.4-1202-jdbc41.jar!/:9.4]
    at org.postgresql.core.VisibleBufferedInputStream.read(VisibleBufferedInputStream.java:71) ~[postgresql-9.4-1202-jdbc41.jar!/:9.4]
    at org.postgresql.core.PGStream.ReceiveChar(PGStream.java:282) ~[postgresql-9.4-1202-jdbc41.jar!/:9.4]
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1718) ~[postgresql-9.4-1202-jdbc41.jar!/:9.4]
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:173) ~[postgresql-9.4-1202-jdbc41.jar!/:9.4]
    ... 61 common frames omitted
Wrapped by: org.postgresql.util.PSQLException: An I/O error occurred while sending to the backend.
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:201) ~[postgresql-9.4-1202-jdbc41.jar!/:9.4]
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:615) ~[postgresql-9.4-1202-jdbc41.jar!/:9.4]
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:465) ~[postgresql-9.4-1202-jdbc41.jar!/:9.4]
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:411) ~[postgresql-9.4-1202-jdbc41.jar!/:9.4]
    at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.executeUpdate(ResultSetReturnImpl.java:208) ~[hibernate-core-4.3.11.Final.jar!/:4.3.11.Final]
    ... 57 common frames omitted
Wrapped by: org.hibernate.exception.JDBCConnectionException: could not execute statement

编辑:

我已经添加了这个并正在测试它:

  spring.datasource.testOnBorrow=true
  spring.datasource.validationQuery=SELECT 1

并删除了autoReconnect

【问题讨论】:

***.com/a/22687418/3093580 以上答案可能有用 试试这个 - 需要 7.5 小时 - 你明天会收到回复 :) 【参考方案1】:

正如@Yuki Yoshida 所说,答案就是这么简单。

我添加了 spring.datasource.validation-query= select 1 spring.datasource.test-on-borrow=true 根据我的配置,它可以工作。

借用测试:

testOnBorrow:默认值:true

是否将验证对象的指示 在从游泳池借来之前。如果对象无法验证, 它将从池中删除,我们将尝试借用 另一个。

并且 验证查询:默认值:对于大多数数据库语言 select 1 否则请参阅 here

验证查询

将用于验证的 SQL 查询 在将它们返回给调用者之前,来自该池的连接。如果 指定,此查询必须是返回的 SQL SELECT 语句 至少一排。如果未指定,连接将由 调用 isValid() 方法。

我实际上已经尝试过了,但我没有明确地将 test-on-borrow 设置为 true,因为它是默认设置。看起来你必须明确设置它。

【讨论】:

isValid() 默认实现?测试连接。如果可能的话,你能分享一下实现细节吗 亲爱的 Ramakrishnan,是的 - isValid 默认实现。有关 isValid() 用法的更多详细信息,请参阅docs.oracle.com/en/database/oracle/oracle-database/12.2/jjucp/…。

以上是关于为啥 spring-boot 和 postgres 连接会在一段时间后断开?的主要内容,如果未能解决你的问题,请参考以下文章

在带有 Spring-boot 的 postgres 中使用整数数组

docker-compose:spring-boot web 服务访问 postgres db 服务

在 postgres spring-boot + eclipselink 中保存为 JSON 数据类型的替代解决方案

连接被拒绝 postgres docker

为啥我用 spring-boot 得到 404 休息

Grafana 与 springboot 和 postgres 的集成