2011-11-18 60 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)看起來像連接對象有問題等

相關問題