Соединение с базой данных неожиданно закрыто с помощью Glassfish, jTDS и SQL Server 2008 - PullRequest
5 голосов
/ 18 ноября 2011

У меня есть приложение Java EE, работающее на Glassfish и подключающееся к MSSQL Server 2008 через jTDS.По неизвестной причине соединение с базой данных неожиданно закрывается во время запросов.Приложение огромно, но вот краткая информация о том, как происходит ошибка:

Во время установки Glassfish с созданием пула соединений с asadmin create-jdbc-connection-pool и asadmin create-jdbc-resource.Класс источника данных - net.sourceforge.jtds.jdbcx.JtdsDataSource.

. Когда Glassfish повышается, он вызывает нашу реализацию ServletContextListener.contextInitialized (), где мы выбираем источник данных из JNDI.Источник данных хранится в статической переменной.

Некоторое время все идет хорошо.Все запросы обрабатываются, и соединение не закрывается.Наше приложение выполняет обработку с использованием EJB-компонентов Timer и MDB (Message Driven Bean).

Это пример реализации 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

В редких случаях мы получаем это страшное исключение (NPE внутри 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)
  ...

Мы не можем найти, почему это происходит,Используемые соединения никогда не будут простаивать более секунды во время запроса.Мы не знаем, кто разрывает связь.Это может быть нестабильность сети, но тогда я думаю, что jTDS должен выдавать только исключения, связанные с сетью, верно?

Другой вариант - это некоторая политика или конфигурация пула соединений Glassfish (возможно, Glassfish преждевременно закрывает физические соединения), но как это сделать?мы отслеживаем это?

Наконец, MS SQL Server 2008 может удаленно разрывать соединения, но как мы можем отслеживать на стороне сервера, чтобы знать, происходит ли это?

Ответы [ 2 ]

2 голосов
/ 23 ноября 2011

У меня было приложение, которое получало эти типы исключений почти точно. Все мои машины были совершенно новыми серверами, и все сетевые карты были настроены на автоматическое определение скорости сети. Все они были подключены к старому коммутатору со скоростью 100 МБ / с в режиме HALF.

Настройка всех машин на этом коммутаторе для явного использования настройки дуплексного соединения HALF со скоростью 100 МБ / с вместо автоматического определения - вот что мне помогло после бесчисленных часов поиска решения. Вам нужно выяснить, какими должны быть ваши настройки подключения, или поэкспериментировать (это будет очевидно, если вы выберете неправильный вариант, потому что вы не сможете подключиться к устройству через удаленный рабочий стол, поэтому убедитесь, что вы можете добраться до физическая машина).

Это довольно низко висящий фрукт, чтобы проверить это. Я установил командное окно с командой ping с одного из рабочих компьютеров, проверяющих связь с сервером базы данных, и мог периодически видеть потерю пакета. Как только я изменил настройки сетевого адаптера и понял все правильно, проблема полностью исчезла. В Интернете есть несколько статей, посвященных этой проблеме. Это трудно отследить, потому что это: 1) периодическое и 2) похоже, что что-то не так с объектами подключения и т. Д.

1 голос
/ 26 ноября 2011

Попробуйте использовать SQL Server Profiler http://msdn.microsoft.com/en-us/library/ms187929.aspx Можно начать с шаблона «Стандартный», поскольку он содержит события: Аудит входа в систему, Аудит выхода из системы, Существующее соединение http://msdn.microsoft.com/en-us/library/ms190176.aspx Iдумаю, что они наиболее важны для вас

...