gpt4 book ai didi

java - 与 Glassfish、jTDS 和 SQL Server 2008 的数据库连接意外关闭

转载 作者:搜寻专家 更新时间:2023-10-31 20:22:50 24 4
gpt4 key购买 nike

我有一个在 Glassfish 上运行并通过 jTDS 连接到 MSSQL Server 2008 的 Java EE 应用程序。由于某些未知原因,数据库连接在请求期间意外关闭。应用程序很大,但这里总结了错误是如何发生的:

在 Glassfish 设置期间,使用 asadmin create-jdbc-connection-poolasadmin create-jdbc-resource 创建连接池。数据源类是 net.sourceforge.jtds.jdbcx.JtdsDataSource

当 Glassfish 启动时,它调用我们的 ServletContextListener.contextInitialized() 实现,我们从 JNDI 获取数据源。数据源存储在静态变量上。

有一段时间,一切都很顺利。所有请求都得到处理,没有连接被关闭。我们的应用程序使用计时器和 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 迭代期间,其他时候是在查询执行期间。

在极少数情况下(一小时内 7 次)我们会遇到此异常:

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)

同样在极少数情况下(一小时内 5 次)我们会遇到此异常:

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 可能会远程断开连接,但我们如何监控服务器端以了解它是否正在发生?

最佳答案

我有一个应用程序几乎完全接收到这些类型的异常。我所有的机器都是全新的服务器,所有网卡都设置为自动感知网络速度。它们都连接到一个 100MB/秒半双工的旧交换机。

在我花了无数小时寻找解决方案后,将该交换机上的所有机器设置为明确使用 100MB/秒的半双工连接设置而不是自动感应对我来说是有效的。您需要找出您的连接设置应该是什么或进行实验(如果您选择了错误的设置,那将是显而易见的,因为您将无法通过远程桌面连接到盒子,因此请确保您可以访问物理机)。

测试这个很容易实现。我设置了一个命令窗口,其中一台工作机器使用 ping 命令对数据库服务器执行 ping 命令,并且可以定期看到数据包丢失。一旦我更改了 NIC 设置并正确设置,问题就完全消失了。网上有几篇文章讨论了这个问题。很难追踪,因为它是:1) 周期性的和 2) 看起来连接对象有问题,等等。

关于java - 与 Glassfish、jTDS 和 SQL Server 2008 的数据库连接意外关闭,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8176631/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com