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

Posted

技术标签:

【中文标题】什么是 java.io.EOFException,消息:无法读取服务器的响应。预期读取 4 个字节,读取 0 个字节【英文标题】:what is java.io.EOFException, Message: Can not read response from server. Expected to read 4 bytes, read 0 bytes 【发布时间】:2012-12-06 16:38:57 【问题描述】:

这个问题已经在 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 秒注意: strong> 部署在同一台服务器上的其他应用程序连接到同一个数据库并使用不同的池运行顺利。

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

最大等待时间: 0(之前为 60 秒)连接验证: 必需验证方法:表名:演示最多验证一次: 40 秒创建重试次数: 1重试间隔: 5 秒最大连接使用量: 5

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

NumConnAcquired: 44919 计数NumConnReleased: 44919 计数NumConnCreated: 9748 计数NumConnDestroyed: 9793 个计数NumConnFailedValidation: 70 个计数NumConnFree: 161 个计数NumConnUsed: -136 个计数

如何 NumConnFree 像我的 Maximum Pool Size = 100 一样变成 161 如何 NumConnUsed 变成 - 136,一个如何 NumConnDestroyed > NumConnCreated ?

【问题讨论】:

尝试在您的应用程序和数据库中使用相同或更小的超时值。例如,如果您的应用程序空闲超时时间高于数据库中的超时时间,您的应用程序将尝试重用已被数据库服务器关闭的连接。 它是否有助于增加池调整大小的数量?查看原因here 【参考方案1】:

这很可能意味着数据库已重新启动或与数据库的网络连接已中断(例如 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 ? 

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

【讨论】:

查看我的编辑。我认为可能存在一些配置问题。【参考方案2】:

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

【讨论】:

这是对 EOFException 的一般解释,但对 mukund 所询问的 JDBC 问题并没有真正的帮助。【参考方案3】:

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

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

由于您使用的是 MySQL,因此您应该使用比实际发出真正的 SQL 查询更轻量的 Connector/J 特定“ping”查询,并将您的验证查询设置为 /* ping */ SELECT 1(ping 部分 @987654321 @)。

【讨论】:

链接“需要准确”已损坏。知道原始页面是怎么说的吗? @mrjink 我再次修复了链接。供将来参考(当 Oracle 再次移动它时),参考 MySQL 的 Connector/J 版本 5.1.3 发行说明,其最后一项包含要使用的语法。【参考方案4】:

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

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

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

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

尝试不同的连接池库只是为了消除连接池的可能性

祝你好运

【讨论】:

在我处理这个问题时,超时值太小了。【参考方案5】:

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

【讨论】:

【参考方案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;

这解决了问题。

【讨论】:

【参考方案7】:

在尝试连接和/或从 mysql 服务器获取一些数据时,在 phpStorm 中出现此错误。复选框“单连接模式”为我修复了问题。 我就把它留在这里。或许这会对未来的一些烈士有所帮助。

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

【讨论】:

我在 PHPStorm 中尝试通过 SSH 连接到 Ubuntu 16.04 虚拟机时遇到此错误。就我而言,问题是我将 VM 的主机名放在“常规”选项卡上的 Host 字段中,而不是像应该的那样放在 localhost 中。 (在我的情况下,使用 single connection mode 似乎并没有以某种方式产生影响。)【参考方案8】:

我也遇到了同样的问题,是因为锁的时间太长了。

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

【讨论】:

【参考方案9】:

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

【讨论】:

以上是关于什么是 java.io.EOFException,消息:无法读取服务器的响应。预期读取 4 个字节,读取 0 个字节的主要内容,如果未能解决你的问题,请参考以下文章

Java 对象流和 java.io.EOFException

java.io.EOFException这是个啥异常应该怎么解决

Java Scoket之java.io.EOFException解决方案

Java Scoket之java.io.EOFException解决方案

java.io.EOFException

java.io.EOFException java.io.ObjectInputStream$PeekInputStream.readFully 错误