什么是java.io.EOFException,错误信息:无法从服务器读取响应。预期读取4个字节,但实际读取了0个字节。

54

这个问题在 Stack Overflow 上被问了几次,在其他网站上也被问了很多次。但是我没有得到满意的答案。

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

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

该应用已经部署了三个月,一直运行良好。
但是在过去的两天中,在登录时出现了以下错误。

部分堆栈跟踪信息

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秒)
连接验证:必需的
验证方法:
表名称:Demo
最多验证一次:40秒
重试创建连接尝试:1
重试间隔:5秒钟
最大连接使用量:5

这样做后,应用程序连续运行了3天。但我从中得出了一个非常奇怪和有趣的结果。在监视连接池时,我发现了这些数字:

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

如何才能使NumConnFree变为161,而我的最大池大小=100
如何才能使NumConnUsed变为负数-136
如何NumConnDestroyed的数量大于 NumConnCreated 的数量


1
尝试在应用程序和数据库中使用相同或更小的超时值。例如,如果您的应用程序的空闲超时时间比数据库的超时时间长,那么您的应用程序将尝试重用已被数据库服务器关闭的连接。 - Adrian
它是否有助于增加池调整大小的数量?在此处查看原因:http://docs.oracle.com/cd/E19316-01/820-4343/abehq/index.html - perissf
11个回答

0
在我们的情况下,由于Docker错误,我们遇到了“无法从服务器读取响应。预期读取4个字节,在连接意外丢失之前读取了0个字节”的错误(在IntelliJ中)。
我们通过简单地运行以下命令来解决这个问题:
docker-compose --profile microservices --compatibility -f docker-compose.services.yml up

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接