Java 连接在非活动时间后挂起
在我的应用程序中,Spring管理数据库访问的连接池。Hibernate使用这些连接进行查询。乍一看,我对池没有任何问题:它可以正确地处理并发客户端和只有一个连接的池。我可以执行很多查询,所以我认为我(或Spring)不会留下打开的连接 我的问题出现在一段时间的不活动之后(有时30分钟,有时超过2小时)。然后,当Hibernate进行一些搜索时,它会持续太久。将log4j级别设置为TRACE,我得到以下日志:Java 连接在非活动时间后挂起,java,oracle,hibernate,spring,jdbc,Java,Oracle,Hibernate,Spring,Jdbc,在我的应用程序中,Spring管理数据库访问的连接池。Hibernate使用这些连接进行查询。乍一看,我对池没有任何问题:它可以正确地处理并发客户端和只有一个连接的池。我可以执行很多查询,所以我认为我(或Spring)不会留下打开的连接 我的问题出现在一段时间的不活动之后(有时30分钟,有时超过2小时)。然后,当Hibernate进行一些搜索时,它会持续太久。将log4j级别设置为TRACE,我得到以下日志: ... 18:27:01 DEBUG nsactionSynchronizationM
...
18:27:01 DEBUG nsactionSynchronizationManager - Retrieved value [org.springframework.orm.hibernate3.SessionHolder@99abd7] for key [org.hibernate.impl.SessionFactoryImpl@7d2897] bound to thread [http-8080-Processor24]
18:27:01 DEBUG HibernateTransactionManager - Found thread-bound Session [org.hibernate.impl.SessionImpl@8878cd] for Hibernate transaction
18:27:01 DEBUG HibernateTransactionManager - Using transaction object [org.springframework.orm.hibernate3.HibernateTransactionManager$HibernateTransactionObject@1b2ffee]
18:27:01 DEBUG HibernateTransactionManager - Creating new transaction with name [com.acjoventut.service.GenericManager.findByExample]: PROPAGATION_REQUIRED,ISOLATION_DEFAULT
18:27:01 DEBUG HibernateTransactionManager - Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@8878cd]
18:27:01 TRACE SessionImpl - setting flush mode to: AUTO
18:27:01 DEBUG JDBCTransaction - begin
18:27:01 DEBUG ConnectionManager - opening JDBC connection
在这里,它被冻结了大约2-10分钟。但接着又说:
18:30:11 DEBUG JDBCTransaction - current autocommit status: true
18:30:11 DEBUG JDBCTransaction - disabling autocommit
18:30:11 TRACE JDBCContext - after transaction begin
18:30:11 DEBUG HibernateTransactionManager - Exposing Hibernate transaction as JDBC transaction [jdbc:oracle:thin:@212.31.39.50:30998:orcl, UserName=DEVELOP, Oracle JDBC driver]
18:30:11 DEBUG nsactionSynchronizationManager - Bound value [org.springframework.jdbc.datasource.ConnectionHolder@843a9d] for key [org.apache.commons.dbcp.BasicDataSource@7745fd] to thread [http-8080-Processor24]
18:30:11 DEBUG nsactionSynchronizationManager - Initializing transaction synchronization
...
在那之后,它工作没有问题,直到另一段时间的不活动。依我看,连接池似乎返回了一个无效/关闭的连接,当Hibernate意识到这一点时,请求另一个到该池的连接
我不知道如何解决这个问题,也不知道我能做些什么来界定它。任何有助于实现这一目标的人都将不胜感激
谢谢
编辑:嗯,这最终是由于防火墙规则。数据库检测到连接丢失,但池(dbcp或c3p0)未丢失。因此,它尝试查询数据库,但没有成功。对我来说仍然奇怪的是,超时时间非常多变。可能规则特别奇怪,或者防火墙不能正常工作。无论如何,我无法访问那台机器,只能等待解释(检查池实现的配置。通常情况下,在关闭连接后,每个连接的配置都是相同的
在您的代码中,您不应该保留连接。获取一个连接,使用它,然后立即关闭。池将确保这不会花费太多。我以前遇到过这样的问题,当数据库位于一个单独的框中,并且中间有一个防火墙,防火墙设置为超时空闲连接 在某些情况下,防火墙会以JDBC端无法检测到的方式切断连接,试图使用它会导致无限阻塞
在我的例子中,它是一个自定义连接池,在从池中返回测试查询之前,它向连接发送了一个测试查询。我将此测试查询配置为有一个超时(使用Statement.setQueryTimeout)这样它就不会无限期地阻塞。解决空闲超时问题的一种方法是使用两个连接池,一个是活动的,另一个是备用的(尚未创建任何连接)。有一个触发时间远小于防火墙\u空闲\u超时的计时器,并在连接池之间切换。我尝试了这个方法,并且它可以正常工作。您必须在数据源中添加一些参数:
更重要的是,添加TestOnBrook和validationQuery,我们解决了类似症状的问题,这些症状也被证明是由防火墙引起的 我们可以通过更改testWhileIdle连接池属性(防止连接空闲)和防火墙关闭连接来解决此问题。请参阅。以下是配置文件persistentce-context.xml中修复此问题的示例:
<property name="testWhileIdle">
<value>true</value>
</property>
<property name="minEvictableIdleTimeMillis">
<value>600000</value>
</property>
<property name="timeBetweenEvictionRunsMillis">
<value>600000</value>
</property>
Spring管理我的连接,因此我不是必须明确调用Connection.close()的人。是吗?正如您所说,我使用的是org.apache.commons.dbcp.BasicDataSource,带有destroy method=“close”。我将对此进行研究。还有两个问题来源:您和数据库服务器之间可能存在防火墙(但空闲TCP连接上的2h超时有点短)。或者您的数据库配置为在一段时间后关闭空闲连接。请参阅DBCP的其他配置选项,以检查是否存在死连接,并定期ping数据库以保持管道打开。至于关闭:否,您不应关闭它,但应结束事务(这将使Spring看到连接可以返回到池)。我不知道为什么您会使用自定义池只发送测试查询。一个简单的连接池和/或容器管理的数据源已经能够做到这一点。例如DBCP和Tomcat JNDI也是如此。请在每个关键字下使用配置文档
validationQuery
。这是在一个项目中(很久以前)这使用了一个定制的连接池,并且在代码部分中确实做了与DBCP中的validationQuery类似的事情。你是对的。问题似乎是一些防火墙规则超出了我的控制。我认为最好的解决方案是改变防火墙行为。谢谢。你如何确定这是否是防火墙问题?我面临一个新的问题类似的问题是dbcp无限期地挂起在我的Spring批处理事务上,并且永远不会返回
09-06-13 @ 16:36:34 [DEBUG] HibernateTransactionManager - Preparing JDBC Connection of Hibernate Session [org.hibernate.impl.SessionImpl@db17ab]
09-06-13 @ 16:36:34 [DEBUG] ConnectionManager - opening JDBC connection
09-06-13 @ 16:52:00 [DEBUG] DataSourceUtils - Setting JDBC Connection
09-06-13 @ 16:52:00 [DEBUG] JDBCTransaction - begin
09-06-13 @ 16:52:00 [DEBUG] JDBCTransaction - current autocommit status: true