什么是java.io.EOFException,消息:无法从服务器读取响应.预期读取 4 个字节,读取 0 个字节



这个问题在SO中被问过几次,在其他网站上也问过很多次。但我没有得到任何满意的答案。

我的问题:
我有一个java Web应用程序,它使用简单的JDBC通过Glassfish应用程序服务器连接到mysql数据库。

我在 glassfish 服务器中使用了具有以下配置的连接池:初始池大小:25
最大池大小:100 池大小调整数量:2
空闲超时:300 秒
最长等待时间:
60,000
毫秒

该应用程序已经部署了过去 3 个月,并且运行也完美无缺。
但是从最近2天开始,登录时会出现以下错误。

部分堆栈跟踪

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

是什么原因导致这个错误突然?我为此浪费了很多时间。

编辑:重新启动服务器后问题仍然存在。根据DBA的两个重要的mysql服务器配置是:
wait_timeout:1800秒
connect_timeout:10秒
注意部署在同一服务器中的其他应用程序连接到同一数据库并使用不同的池运行平稳。

编辑-2 :在阅读了很多东西并期待一些积极的结果后,我对我的连接池进行了这些更改。

最长等待时间: 0 (以前是 60 秒)
连接验证 : 必需
验证方法: 表 表
名称: 演示
最多验证一次: 40 秒创建重试次数: 1
重试间隔: 5 秒

最大连接使用量 :5

这是有效的,因为应用程序持续运行了 3 天。但是我得到了一个非常奇怪和有趣的结果。在监视连接池时,我发现了以下数字:

获得的次数 : 44919 计数 已释放的编号 :44919 计数 已创建数 : 9748
计数 已销毁的编号连接数 : 9793 计数 连接数失败验证 : 70 计数 连接数免费 : 161 计数已连接-136 计数




NumConnFree怎么能像我Maximum Pool Size = 100一样变成161
NumConnUsed怎么会变成负数-136
NumConnDestroyed怎么>NumConnCreated

连接失败,可能是由于防火墙空闲超时等。如果您没有将 JDBC 驱动程序配置为在失败时重新连接,则除非您打开新连接,否则此错误不会消失。

如果您使用的是数据库连接池(您正在使用一个,对吗?),那么您可能希望启用它的连接检查功能,例如发出查询以检查连接是否正常工作,然后再将其交还给应用程序。在Apache commons-dbcp中,这被称为validationQuery,通常设置为简单的内容,如SELECT 1

由于您使用的是 MySQL,因此您应该使用特定于连接器/J 的"ping"查询,该查询比实际发出真正的 SQL 查询更轻量级,并将验证查询设置为/* ping */ SELECT 1(ping 部分需要精确)。

这是 Java 中的 EndOfFileException,当光标起点位于端点上或数据库连接由于某些意外异常而关闭时发生。

这很可能意味着数据库已重新启动或与数据库的网络连接已断开(例如,NAT 连接已超时)...并且您的 Web 应用程序正在尝试使用过时的数据库连接。

如果重新启动 Web 容器后问题仍然存在,则可能是更严重的情况。


您问了以下问题:

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 ? 

从表面上看,这些都没有意义。 但是,它们可能只是某些使用计数器以非线程安全方式更新的结果。 这不一定与您的原始问题有关。

虽然我没有明确的解决方案,但似乎有什么东西干扰了应用程序服务器和数据库之间的通信。以下是您可以尝试隔离问题的几件事:

  • 尝试确定这是 mysql 问题还是 java 代码问题。尝试使用命令行工具从与应用服务器相同的主机连接到 mysql,并发出类似的 SQL 来执行登录。使用执行选择的简单 Java 代码进行测试,将其部署到相同的基础架构,看看会发生什么等。还要检查mysql服务器日志,看看你是否能找到任何有用的东西

  • 有两种方式关闭空闲连接:通过应用程序服务器内部运行的连接池代码,或者通过 mysql 本身。确保检查两端的配置

  • 检查最近是否有任何网络基础结构配置已更改。是否有任何新的防火墙规则干扰应用程序服务器<->mysql 连接?是否有任何设置禁止打开 TCP 连接空闲时间超过 X 的时间?

  • 尝试使用不同的连接池库,以消除它是连接池的可能性

祝你好运

这可能是与防火墙相关的问题。

我遇到了这个问题,但我无法在 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;
}

这解决了问题。

在尝试连接和/或从 mysql 服务器获取一些数据时在 PHPStorm 中出现此错误。复选框"单一连接模式"为我解决了问题。 我就把它留在这里。也许这会在未来帮助一些殉道者。

https://www.jetbrains.com/help/phpstorm/configuring-database-connections.html

我遇到了同样的问题,它是由锁定引起的时间太长。

我们有一个很长的转换 A,如果执行它,另一个转换将被锁定 util transcation A 完成,所以其他的总是被我们的 mysql 工具(pt-kill)杀死

就我而言,它是java mysql驱动程序/连接器版本。 即(即使服务器是版本 8)当我使用 mysql 驱动程序/连接器版本 5.1.44 时,它开始工作。

可能是服务器连接已满 尝试减少服务器连接或修改最大连接参数

在我们的例子中,我们收到错误"无法从服务器读取响应。由于 Docker 错误,预期读取 4 个字节,在连接意外丢失之前读取 0 个字节"(在 IntelliJ 中)。

我们通过简单地运行来修复它:

docker-compose --profile microservices --compatibility -f docker-compose.services.yml up

相关内容

  • 没有找到相关文章

最新更新