为什么在一段时间后,Spring Boot 和 Postgres 的连接会中断?

22 浏览
0 Comments

为什么在一段时间后,Spring Boot 和 Postgres 的连接会中断?

我使用gradle在Spring Boot中运行,使用tomcat-connection-pool连接池。所有标准的spring-boot-tools都在使用中。我在该web服务器上运行了几个soap-webservice。当测试服务器负载时,一切都运行正常。但是,在大约7.5小时不做任何操作之后,出现了以下异常。虽然是一个超时异常,但我试图通过以下方法来防止它发生:\n

    \n

  • spring.datasource.url=jdbc:postgresql://mydb?autoReconnect=true
  • \n

  • 我对某些语句使用@transactional。但是通常我只使用spring-boot的JPA-Repository
  • \n

  • 连接由tomcat-connection-pool管理,所以没有空闲连接问题。
  • \n

  • 当我重新启动应用服务器时,一切都会再次正常运行。
  • \n

\n我的数据库服务器运行在PostgreSQL 9.4.1 on x86_64-unknown-linux-gnu上,数据库和应用服务器之间没有防火墙。我需要tcp_keep alives吗?\n为什么连接在一段时间后中断,且无法恢复?\n我的应用属性:\n

#
# [ 数据库配置部分 ]
#
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

\n


\n

2015-09-29 11:58:50.598  INFO 10498 --- [nio-9092-exec-1] o.a.c.c.C.[Tomcat].[localhost].[/]       : 初始化Spring FrameworkServlet 'dispatcherServlet'
2015-09-29 11:58:50.598  INFO 10498 --- [nio-9092-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': 初始化开始
2015-09-29 11:58:50.674  INFO 10498 --- [nio-9092-exec-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': 初始化完成,耗时76毫秒

\n


\n

2015-09-29 19:23:03.777  WARN 10498 --- [ool-3-thread-16] o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL错误: 0, SQL状态: 08006
2015-09-29 19:23:03.779 ERROR 10498 --- [ool-3-thread-16] o.h.engine.jdbc.spi.SqlExceptionHelper   : 发送到后端时发生I/O错误。
2015-09-29 19:23:03.785  INFO 10498 --- [ool-3-thread-16] o.h.e.j.b.internal.AbstractBatchImpl     : HHH000010: 释放批处理时仍然包含JDBC语句
2015-09-29 19:23:03.836 ERROR 10498 --- [ool-3-thread-16] o.s.orm.jpa.JpaTransactionManager        : 回滚异常覆盖了提交异常
java.net.SocketException: 连接超时
    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
包装器: org.postgresql.util.PSQLException: 发送到后端时发生I/O错误。
    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
包装器: org.hibernate.exception.JDBCConnectionException: 无法执行语句

\n编辑:\n我已经添加了以下内容,并正在进行测试:\n spring.datasource.testOnBorrow=true\n spring.datasource.validationQuery=SELECT 1\n\n并删除了autoReconnect

0
0 Comments

问题:为什么在一定时间后,Spring Boot和PostgreSQL连接会断开?

解决方法:

根据Yoshida的建议,解决方法非常简单。只需要在配置中添加以下内容:

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

其中test-on-borrow参数表示在从连接池借用连接之前是否进行验证,默认为true。如果连接验证失败,连接将被从连接池中删除,并尝试借用另一个连接。

validationQuery参数表示在将连接返回给调用者之前用于验证连接的SQL查询。如果指定了validationQuery,则该查询必须是至少返回一行的SQL SELECT语句。如果未指定validationQuery,则将调用isValid()方法进行连接验证。

在这里,我已经尝试过这种方法,但没有显式设置test-on-borrow为true,因为它是默认值。看来必须要显式设置这个参数。

isValid()方法默认实现了连接的测试。具体实现细节请参考Oracle官方文档:docs.oracle.com/en/database/oracle/oracle-database/12.2/jjucp/…

0