2011-11-18 63 views
5

我有一个Java EE应用程序在Glassfish运行,并通过JTDS连接MSSQL Server 2008的关闭。由于某些未知原因,数据库连接在请求期间意外关闭。该应用程序是巨大的,但这里是错误发生的概要:数据库连接意外与Glassfish的,JTDS和SQL Server 2008

在Glassfish安装过程中,创建一个连接池asadmin create-jdbc-connection-poolasadmin create-jdbc-resource。数据源类是net.sourceforge.jtds.jdbcx.JtdsDataSource

当Glassfish的上升,它要求我们实施ServletContextListener.contextInitialized的(),我们取从JNDI数据源。数据源存储在一个静态变量中。

有一段时间,一切都很好。所有请求都被处理并且没有连接被关闭。我们的应用程序使用Timer和MDB(消息驱动Bean)EJB来执行处理。

这是一个示例onMessage()实现:

public void onMessage(Message message) { 
    this.message = message; 
    this.connection = dataSource.getConnection(userName, password); 
    try { 
    doQuery1(); 
    doTransaction1(); 
    doTransaction2(); 
    doQuery2(); 
    doQuery3(); 
    } finally { 
    this.connection.close(); 
    this.connection = null; 
    } 
} 

最后,我们开始出现以下情况例外(发生在一小时内约100次):

java.sql.SQLException: Invalid state, the Connection object is closed. 
    at net.sourceforge.jtds.jdbc.ConnectionJDBC2.checkOpen(ConnectionJDBC2.java) 
    at net.sourceforge.jtds.jdbc.ConnectionJDBC2.prepareStatement(ConnectionJDBC2.java) 
    at net.sourceforge.jtds.jdbc.ConnectionJDBC2.prepareStatement(ConnectionJDBC2.java) 
    at com.sun.gjc.spi.base.ConnectionHolder.prepareStatement(ConnectionHolder.java:475) 
    at com.acme.myejbs.MyMDB.doQuery2(MyMDB.java:123) 
    at com.acme.myejbs.MyMDB.onMessage(MyMDB.java:614) 
    at sun.reflect.GeneratedMethodAccessor115.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java) 
    at java.lang.reflect.Method.invoke(Method.java) 
    at com.sun.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1011) 
    ... 
    at $Proxy92.onMessage(Unknown Source) 
    at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java) 
    at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:77) 
    at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:555) 

唯一的例外发生在随机JDBC调用。有时候是在ResultSet迭代期间,在查询执行期间的其他时间。 (一小时内5次)

java.sql.SQLException: Error in allocating a connection. Cause: This Managed Connection is not valid as the phyiscal connection is not usable 
    at com.sun.gjc.spi.base.DataSource.getConnection(DataSource.java:136) 
    at com.acme.myejbs.MyMDB.onMessage(MyMDB.java:614) 
    at sun.reflect.GeneratedMethodAccessor115.invoke(Unknown Source) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java) 
    at java.lang.reflect.Method.invoke(Method.java) 
    at com.sun.enterprise.security.application.EJBSecurityManager.runMethod(EJBSecurityManager.java:1011) 
    ... 
    at $Proxy92.onMessage(Unknown Source) 
    at com.sun.messaging.jms.ra.OnMessageRunner.run(OnMessageRunner.java) 
    at com.sun.enterprise.connectors.work.OneWork.doWork(OneWork.java:77) 
    at com.sun.corba.ee.impl.orbutil.threadpool.ThreadPoolImpl$WorkerThread.run(ThreadPoolImpl.java:555) 

此外,在极少数情况下,我们得到这个异常:

在极少数情况下(一小时内7次),我们得到这个异常

java.sql.SQLException: I/O Error: Connection reset by peer: socket write error 
    at net.sourceforge.jtds.jdbc.TdsCore.executeSQL(TdsCore.java) 
    at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQLQuery(JtdsStatement.java) 
    at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeQuery(JtdsPreparedStatement.java) 
    at com.acme.myejbs.MyMDB.doQuery2(MyMDB.java:126) 
    at com.acme.myejbs.MyMDB.onMessage(MyMDB.java:614) 
    ... 
Caused by: java.net.SocketException: Connection reset by peer: socket write error 
    at java.net.SocketOutputStream.socketWrite0(Native Method) 
    at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java) 
    at java.net.SocketOutputStream.write(SocketOutputStream.java) 
    at java.io.DataOutputStream.write(DataOutputStream.java) 
    at net.sourceforge.jtds.jdbc.SharedSocket.sendNetPacket(SharedSocket.java) 
    at net.sourceforge.jtds.jdbc.RequestStream.putPacket(RequestStream.java) 
    at net.sourceforge.jtds.jdbc.RequestStream.flush(RequestStream.java) 
    ... 44 more 

在极少数情况下,我们得到这个可怕的例外(内JTDS NPE):

java.lang.NullPointerException 
    at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeQuery(JtdsPreparedStatement.java) 
    at com.acme.myejbs.MyMDB.doQuery2(MyMDB.java:126) 
    at com.acme.myejbs.MyMDB.onMessage(MyMDB.java:614) 
    ... 

我们找不到为什么会这样。请求期间使用的连接永远不会空闲超过一秒钟。我们不知道谁在断开连接。这可能是网络不稳定,但是我认为jTDS应该只产生与网络相关的异常,对吧?

另一种选择是Glassfish的连接池的一些策略或配置(也许GlassFish是过早地关闭物理连接),但我们怎么可以跟踪它?

最后,MS SQL Server 2008的可以远程连接下探,但我们怎么可以监视服务器端知道它是怎么回事?

+0

不要的问题也发生使用微软的JDBC驱动程序时? – extraneon

+0

@extraneon我们没有测试Microsoft JDBC驱动程序。有一个基于jTDS的整个持久层,切换到MS需要几天时间才能完成。 – fernacolo

+0

您的代码是捕捉/忽略SQLExceptions吗?你使用的是基本的数据源还是连接池? –

回答

2

我不得不接受这些类型的异常正是近一个应用程序。我的所有机器都是全新的服务器,所有网卡都设置为自动感知网络速度。他们都连接到一个100MB /秒半双工的旧开关。

设置所有的机器该交换机上明确地使用了100MB /秒半双工连接设置,而不是自动感应是我做寻找解决无数个小时后什么工作。您需要了解您的连接设置应该是什么或者做了哪些实验(如果您选择错误的连接设置会很明显,因为您无法通过远程桌面连接到该设备,所以请确保您可以访问物理机器)。

这是非常低的挂果测试这一点。我使用来自其中一台工作站计算机的ping命令设置了一个命令窗口,该命令可以ping数据库服务器,并可以定期查看丢包情况。一旦我改变了网卡的设置并把它弄对了,问题就完全消失了。在互联网上有几篇关于讨论这个问题的文章。这是很难追查,因为它是:1)周期性和2)看起来像连接对象有问题等

相关问题