2011-11-18 31 views
5

Tôi có một ứng dụng Java EE chạy trên Glassfish và kết nối với MSSQL Server 2008 thông qua jTDS. Đối với một số lý do không rõ, kết nối cơ sở dữ liệu trở nên bất ngờ bị đóng trong các yêu cầu. Ứng dụng này rất lớn, nhưng dưới đây là tóm tắt về cách lỗi xảy ra:Kết nối cơ sở dữ liệu bất ngờ bị đóng với Glassfish, jTDS và SQL Server 2008

Trong khi thiết lập Glassfish, tạo hồ bơi kết nối với asadmin create-jdbc-connection-poolasadmin create-jdbc-resource. Lớp nguồn dữ liệu là net.sourceforge.jtds.jdbcx.JtdsDataSource.

Khi Glassfish tăng lên, nó gọi thực hiện ServletContextListener.contextInitialized() của chúng tôi, nơi chúng tôi tìm nạp nguồn dữ liệu từ JNDI. Nguồn dữ liệu được lưu trữ trên một biến tĩnh.

Trong một thời gian, mọi thứ diễn ra tốt đẹp. Tất cả các yêu cầu được xử lý và không có kết nối nào bị đóng. Ứng dụng của chúng tôi thực hiện việc xử lý bằng cách sử dụng các EJB thời gian và MDB (Message Driven Bean).

Đây là một thực hiện mẫu 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; 
    } 
} 

Cuối cùng, chúng tôi bắt đầu để có được những ngoại lệ sau đây (xảy ra khoảng 100 lần trong một giờ):

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) 

Trường hợp ngoại lệ xảy ra tại JDBC ngẫu nhiên cuộc gọi. Đôi khi là trong lần lặp ResultSet, các thời điểm khác trong khi thực hiện truy vấn.

Trong những trường hợp rất hiếm (7 lần trong một giờ), chúng tôi có được ngoại lệ này:

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) 

Cũng trong trường hợp rất hiếm (5 lần trong một giờ), chúng tôi có được ngoại lệ này:

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 

Trong trường hợp hiếm hoi, chúng tôi có được ngoại lệ này đáng sợ (NPE bên jTDS):

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) 
    ... 

chúng tôi không thể tìm thấy lý do tại sao điều này xảy ra. Các kết nối được sử dụng không bao giờ trở nên không hoạt động trong hơn một giây trong khi yêu cầu. Chúng tôi không biết ai đang bỏ kết nối. Nó có thể là mạng không ổn định, nhưng sau đó tôi đoán jTDS nên năng suất chỉ có ngoại lệ liên quan đến mạng, phải không?

Một tùy chọn khác là một số chính sách hoặc cấu hình của hồ bơi kết nối Glassfish (có lẽ Glassfish đang đóng kết nối vật lý sớm), nhưng làm thế nào chúng ta có thể theo dõi nó?

Cuối cùng, MS SQL Server 2008 có thể từ xa bỏ kết nối, nhưng làm cách nào chúng tôi có thể theo dõi phía máy chủ để biết điều đó có xảy ra không?

+0

Đừng những vấn đề cũng xảy ra khi sử dụng trình điều khiển JDBC Microsofts? – extraneon

+0

@extraneon Chúng tôi đã không kiểm tra trình điều khiển Microsoft JDBC. Có một lớp toàn bộ persistence dựa trên jTDS và chuyển sang MS sẽ mất một vài ngày để hoàn thành. – fernacolo

+0

Mã của bạn có đang bắt/bỏ qua SQLExceptions không? Bạn đang sử dụng một DataSource cơ bản hoặc một kết nối? –

Trả lời

2

Tôi đã có một ứng dụng nhận được các loại ngoại lệ này gần như chính xác. Tất cả các máy của tôi đều là các máy chủ hoàn toàn mới và tất cả các card mạng được thiết lập để tự động cảm nhận tốc độ mạng. Tất cả chúng đều được kết nối với một công tắc cũ là 100MB/giây HALF duplex.

Đặt tất cả các máy trên công tắc đó để sử dụng rõ ràng cài đặt kết nối kép HALF 100MB/giây thay vì tự động cảm nhận được những gì đã làm việc cho tôi sau khi thực hiện vô số giờ tìm kiếm giải pháp. Bạn sẽ cần phải tìm hiểu cài đặt kết nối của bạn sẽ là gì hoặc thử nghiệm (sẽ rõ ràng nếu bạn chọn sai vì bạn sẽ không thể kết nối với hộp trên máy tính để bàn từ xa, vì vậy hãy đảm bảo bạn có thể truy cập máy vật lý).

Đây là loại quả treo khá thấp để kiểm tra điều này. Tôi thiết lập một cửa sổ lệnh với lệnh ping từ một trong các máy công nhân ping máy chủ cơ sở dữ liệu và có thể thấy mất gói tin định kỳ. Một khi tôi thay đổi các thiết lập NIC và nhận được nó đúng, vấn đề đã biến mất hoàn toàn. Có một số bài viết về trên internet thảo luận về vấn đề này. Rất khó để theo dõi vì đó là: 1) định kỳ và 2) có vẻ như có sự cố với các đối tượng kết nối, v.v.

Các vấn đề liên quan