【问题标题】:Glassfish, PostgreSQL and closed connectionsGlassfish、PostgreSQL 和封闭连接
【发布时间】:2012-06-22 08:28:18
【问题描述】:

我们有一个使用 JPA (Hibernate) 在 Glassfish 上使用 MySQL 的应用程序,该应用程序运行良好。

然后我们切换到 PostgreSQL,几乎一切正常。我们遇到的唯一问题是,应用程序在一段时间后停止响应并抛出异常,因为与 DB 的连接已关闭:

[#|2012-06-19T21:51:22.050+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=38;_ThreadName=Thread-2;|4816089 [p: thread-pool-1; w: 21] WARN org.hibernate.util.JDBCExceptionReporter - SQL Error: 0, SQLState: 08006
[#|2012-06-19T21:51:22.050+0200|SEVERE|glassfish3.1.2|javax.enterprise.system.std.com.sun.enterprise.server.logging|_ThreadID=38;_ThreadName=Thread-2;|4816089 [p: thread-pool-1; w: 21] ERROR org.hibernate.util.JDBCExceptionReporter - An I/O error occured while sending to the backend.
[#|2012-06-19T21:51:22.052+0200|SEVERE|glassfish3.1.2|javax.enterprise.resource.resourceadapter.com.sun.enterprise.resource|_ThreadID=38;_ThreadName=Thread-2;|RAR5031:System Exception
javax.resource.spi.LocalTransactionException: This connection has been closed.
        at com.sun.gjc.spi.LocalTransactionImpl.rollback(LocalTransactionImpl.java:134)
        at com.sun.enterprise.resource.ConnectorXAResource.rollback(ConnectorXAResource.java:213)
        at com.sun.enterprise.transaction.JavaEETransactionImpl.rollback(JavaEETransactionImpl.java:571)
        at com.sun.enterprise.transaction.JavaEETransactionManagerSimplified.rollback(JavaEETransactionManagerSimplified.java:893)
        at com.sun.enterprise.transaction.UserTransactionImpl.rollback(UserTransactionImpl.java:234)
        at ch.ethz.id.wai.lakshmi.engine.common.TransactionHelper.rollbackTransaction(TransactionHelper.java:43)
        at ch.ethz.id.wai.lakshmi.stdcmp.tracking.StandardTracking.updateStatus(StandardTracking.java:50)
        at ch.ethz.id.wai.lakshmi.engine.ejb.LakshmiServerBean.updateTrackingStatus(LakshmiServerBean.java:992)
        at ch.ethz.id.wai.lakshmi.engine.ejb.LakshmiServerBean.executeNextWorkflowStep(LakshmiServerBean.java:771)
        at ch.ethz.id.wai.lakshmi.engine.ejb.LakshmiServerBean.executeNextWorkflowStep(LakshmiServerBean.java:683)
        at ch.ethz.id.wai.lakshmi.engine.ejb.LakshmiServerBean.continueWorkflow(LakshmiServerBean.java:602)
        at ch.ethz.id.wai.lakshmi.engine.ejb.LakshmiServerBean.processSubmitOrderRequest(LakshmiServerBean.java:487)
        at ch.ethz.id.wai.lakshmi.engine.ejb.LakshmiServerBean.onMessage(LakshmiServerBean.java:360)
        at sun.reflect.GeneratedMethodAccessor133.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.glassfish.ejb.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1052)
        at org.glassfish.ejb.security.application.EJBSecurityManager.invoke(EJBSecurityManager.java:1124)
        at com.sun.ejb.containers.BaseContainer.invokeTargetBeanMethod(BaseContainer.java:4180)
        at com.sun.ejb.containers.BaseContainer.__intercept(BaseContainer.java:5368)
        at com.sun.ejb.containers.BaseContainer.intercept(BaseContainer.java:5348)
        at com.sun.ejb.containers.MessageBeanContainer.deliverMessage(MessageBeanContainer.java:1099)
        at com.sun.ejb.containers.MessageBeanListenerImpl.deliverMessage(MessageBeanListenerImpl.java:81)
        at com.sun.enterprise.connectors.inbound.MessageEndpointInvocationHandler.invoke(MessageEndpointInvocationHandler.java:171)
        at $Proxy264.onMessage(Unknown Source)
        at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java:260)
        at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:114)
        at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.performWork(ThreadPoolImpl.java:497)
        at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:540)
Caused by: org.postgresql.util.PSQLException: This connection has been closed.
        at org.postgresql.jdbc2.AbstractJdbc2Connection.checkClosed(AbstractJdbc2Connection.java:714)
        at org.postgresql.jdbc2.AbstractJdbc2Connection.rollback(AbstractJdbc2Connection.java:731)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.postgresql.ds.jdbc23.AbstractJdbc23PooledConnection$ConnectionHandler.invoke(AbstractJdbc23PooledConnection.java:352)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at org.postgresql.ds.jdbc23.AbstractJdbc23PooledConnection$ConnectionHandler.invoke(AbstractJdbc23PooledConnection.java:352)
        at $Proxy161.rollback(Unknown Source)
        at com.sun.gjc.spi.LocalTransactionImpl.rollback(LocalTransactionImpl.java:128)
        ... 28 more

我们以同样的方式为 MySQL 和 PostgreSQL 创建连接池:

asadmin create-jdbc-connection-pool \
    --restype javax.sql.DataSource \
    --datasourceclassname org.postgresql.jdbc2.optional.PoolingDataSource \
    --property URL='jdbc:postgresql://127.0.0.1:5432/doi':serverName=localhost:databaseName=doi:user=doi:password=******** doi

和

asadmin create-jdbc-connection-pool \
    --restype javax.sql.DataSource \
    --datasourceclassname com.mysql.jdbc.jdbc2.optional.MysqlConnectionPoolDataSource \
    --property serverName=127.0.0.1:dataBaseName=doi:user=doi:********=doi:schema=doi doi

如何配置数据池以关闭空闲连接或使其保持活动状态并避免关闭连接错误?

【问题讨论】:

  • (未测试)可能将 tcpKeepAlive=true 添加到 jdbc 连接字符串
  • 我会尝试,但实际上连接池应该能够管理连接而不必让它们始终处于活动状态
  • 这个问题看起来惊人地相似:stackoverflow.com/questions/11417504/…

标签: java postgresql glassfish database-connection connection-pooling


【解决方案1】:

Pg 连接应无限期保持有效,只要:

  • 数据库服务器未停止或重新启动
  • DB 服务器的 IP 没有变化
  • 客户端和服务器之间没有连接跟踪或 NAT 路由器

后两者不是问题,因为您连接到 localhost,因此您不需要任何特殊措施来保持连接有效。

我有点怀疑您使用的是 org.postgresql.ds.PGSimpleDataSource 。 Glassfish 有自己的池,您可能应该使用计划 org.postgresql.datasource.Datasource 。您很可能正在进行两层池化,结果可能令人困惑。您会注意到the PgJDBC documentation 中的声明:

这里提供的池化数据源实现并不是最 功能丰富的世界。除其他外,连接永远不会 关闭,直到游泳池本身关闭;没有办法缩小 水池。同样,为非默认用户请求的连接 配置的用户未汇集。它的错误处理有时不能 从池中删除断开的连接。一般来说不是 建议使用 PostgreSQL™ 提供的连接池。查看 您的应用程序服务器或查看优秀的 jakarta commons DBCP 项目。

请改用org.postgresql.ds.PGSimpleDataSource,看看是否能解决您的问题。

【讨论】:

  • 其实我用的是org.postgresql.ds.PGPoolingDataSource。我会尝试org.postgresql.datasource.Datasource。
  • @Matteo 感谢您回来并确认。很高兴能提供帮助。
  • @CraigRinger, org.postgresql.ds.PGSimpleDataSource “不执行连接池”。我不明白你为什么建议它。文档链接:jdbc.postgresql.org/documentation/publicapi/org/postgresql/ds/…
猜你喜欢
  • 1970-01-01
  • 2014-09-19
  • 2020-08-30
  • 2018-11-26
  • 1970-01-01
  • 1970-01-01
  • 2014-07-01
  • 2019-04-22
  • 1970-01-01
相关资源
最近更新 更多