Подтвердить что ты не робот

Что такое java.io.EOFException, Message: Не удается прочитать ответ с сервера. Ожидалось читать 4 байта, читать 0 байт

Этот вопрос задавали пару раз в SO и много раз на других сайтах. Но ответа я не получил.

Моя проблема:
У меня есть веб-приложение java, которое использует простой JDBC для подключения к базе данных mysql через сервер приложений Glassfish.

Я использовал пул соединений на сервере Glassfish со следующими конфигурациями:
Начальный размер пула: 25
Максимальный размер бассейна: 100
Pool Resize Количество: 2
Idle Timeout: 300 секунд
Максимальное время ожидания: 60 000 миллисекунд

Приложение было развернуто в течение последних 3 месяцев, и оно работает безупречно.
Но с последних 2 дней на момент входа в систему появляется следующая ошибка.

Частичный StackTrace

com.mysql.jdbc.exceptions.MySQLNonTransientConnectionException: No operations allowed after connection closed.Connection was implicitly closed due to underlying exception/error:  

** BEGIN NESTED EXCEPTION **  

com.mysql.jdbc.CommunicationsException  
MESSAGE: Communications link failure due to underlying exception:  

** BEGIN NESTED EXCEPTION **  

java.io.EOFException  
MESSAGE: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.  

STACKTRACE:  

java.io.EOFException: Can not read response from server. Expected to read 4 bytes, read 0 bytes before connection was unexpectedly lost.  
at com.mysql.jdbc.MysqlIO.readFully(MysqlIO.java:1997)  
at com.mysql.jdbc.MysqlIO.reuseAndReadPacket(MysqlIO.java:2411)  
at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:2916)  
at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:1631)  
at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:1723)  
at com.mysql.jdbc.Connection.execSQL(Connection.java:3256)  
at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1313)  
at com.mysql.jdbc.PreparedStatement.executeQuery(PreparedStatement.java:1448)  
............  
............  
my application traces....  

Что вызвало эту ошибку внезапно? Я потерял много времени для этого.

EDIT: Проблема сохраняется даже после перезапуска сервера. В соответствии с DBA две важные конфигурации сервера mysql:
wait_timeout: 1800 секунд
connect_timeout: 10 секунд
ПРИМЕЧАНИЕ. Другие приложения, развернутые на одном сервере, подключающиеся к одной базе данных и использующие разные пулы, работают плавно.

EDIT-2: После прочтения многих вещей и ожиданий какого-то положительного результата я внес эти изменения в пул соединений.

Макс. время ожидания: 0 (раньше это было 60 секунд)
Проверка подключения: Требуется | Метод проверки: таблица
Имя таблицы: Демо-версия Подтвердить как минимум: 40 секунд
попытки повторной попытки создания: 1
Интервалы повторения: 5 секунд
Максимальное использование подключения: 5

И это работало, так как приложение работает в течение 3 дней. Но у меня получился очень странный и интересный результат. Наблюдая за пулом соединений, я нашел эти цифры:

NumConnAcquired: 44919 Count
NumConnReleased: 44919 Count
NumConnCreated: 9748 Count
NumConnDestroyed: 9793 Count
NumConnFailedValidation: 70 Count
NumConnFree: 161 граф
NumConnUsed: -136 Count

Как может NumConnFree стать 161, поскольку у меня есть Maximum Pool Size = 100 ?
Как может NumConnUsed стать -136, отрицательное число ?
Как может NumConnDestroyed NumConnCreated ?

4b9b3361

Ответ 1

Соединение завершилось неудачно, возможно из-за тайм-аута брандмауэра и т.д. Если у вас нет драйвера JDBC, настроенного на повторное подключение к ошибке, эта ошибка не исчезнет, ​​если вы не откроете новое соединение.

Если вы используете пул соединений с базой данных (вы используете один, правда?), то вы, вероятно, захотите включить его функции проверки соединения, такие как выдача запроса, чтобы проверить, работает ли соединение, прежде чем передать его обратно приложение. В Apache commons-dbcp это называется validationQuery и часто устанавливается на что-то простое, например SELECT 1.

Поскольку вы используете MySQL, вы должны использовать запрос "ping" для Connector/J-specific, который имеет меньший вес, чем фактический выпуск истинного SQL-запроса, и установите ваш запрос проверки на /* ping */ SELECT 1 (часть ping должно быть точно).

Ответ 2

Скорее всего, это означает, что база данных перезагрузилась или сетевое соединение с базой данных было нарушено (например, время соединения NAT было отключено)... и ваш webapp пытается использовать устаревшее соединение с базой данных.

Если проблема повторится после перезапуска веб-контейнера, это может быть что-то более серьезное.


Вы спросили следующее:

How can the NumConnFree become 161 as I have Maximum Pool Size = 100 ?
How can the NumConnUsed become -136, a negative number ?
How can the NumConnDestroyed > NumConnCreated ? 

На первый взгляд это не имеет смысла. Однако они могут быть просто результатом того, что некоторые счетчики использования обновляются небезопасным способом. Это не обязательно связано с вашей исходной проблемой.

Ответ 3

Это EndOfFileException в java, происходит, когда начальная точка курсора находится в конечной точке или когда соединение с базой данных закрыто из-за какого-то неожиданного исключения.

Ответ 4

Пока у меня нет окончательных решений, кажется, что что-то мешает взаимодействию между сервером приложений и db. Ниже приведены несколько вещей, которые вы можете попытаться изолировать проблемы:

  • Попробуйте определить, есть ли проблема mysql или проблема с java-кодом. Попробуйте подключиться к mysql с помощью инструмента командной строки с того же хоста, что и сервер приложений, и выпустить аналогичный SQL для входа в систему. Протестируйте с помощью простого java-кода, который делает выбор, разворачивает его в той же инфраструктуре, видит, что произойдет и т.д. Также проверьте журнал сервера mysql, посмотрите, можете ли вы найти что-нибудь полезное

  • Существует два способа: закрытие незанятого соединения: по коду пула соединений, который запускается внутри сервера приложений, или самому mysql. Убедитесь, что вы проверяете конфигурацию с обеих сторон.

  • Проверьте, изменилась ли какая-либо конфигурация сетевой инфраструктуры в последнее время. Было ли какое-либо новое правило брандмауэра вмешиваться в соединение с сервером приложений ↔ mysql? Были ли какие-либо настройки, запрещающие открытое TCP-соединение на холостом ходу дольше X?

  • Попробуйте использовать другую библиотеку пула соединений, чтобы исключить возможность объединения пулов

Удачи.

Ответ 5

Это может быть проблема с Firewall.

Ответ 6

У меня была эта проблема, но мне не удалось внести изменения в конфигурацию базы данных MySQL. Поэтому я убедился, что в моем классе соединителей sql соединение всегда закрывается до его повторного запуска. Что-то вроде:

public static Connection getConnection() {

    if (DatabaseConnnector.conn == null) {
        initConn();
    } else {
        try {
            DatabaseConnnector.conn.close();          
        } catch (SQLException e) {
            e.printStackTrace();
        }
          initConn();
    }
    return DatabaseConnnector.conn;
}

И это решило проблему.