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

muk*_*und 43 java mysql connection pool glassfish

这个问题在SO中被问了好几次,在其他网站上已经多次询问过.但我没有得到任何令人满意的答案.

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

我在glassfish服务器中使用了以下配置的连接池:
初始池大小:25
最大池大小:100
池大小调整数量:2
空闲超时: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....  
Run Code Online (Sandbox Code Playgroud)

是什么原因导致了这个错误 我已经失去了很多时间.

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

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

最大等待时间: 0(以前是60秒)
连接验证:必需
验证方法:
表名:演示
验证Atmost一旦: 40秒
创作重试尝试: 1
个试间隔: 5秒
最大连接用法: 5

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

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

怎么NumConnFree像我一样成为161 Maximum Pool Size = 100
如何将可以NumConnUsed成为-136,一个
怎么可以NumConnDestroyed > NumConnCreated

Chr*_*ltz 9

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

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

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


Ste*_*n C 8

它很可能意味着数据库已重新启动或与数据库的网络连接已断开(例如,NAT连接已超时)...并且您的webapp正在尝试使用陈旧的数据库连接.

如果重新启动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 ? 
Run Code Online (Sandbox Code Playgroud)

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


Pun*_*eet 6

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

  • 这是对EOFException的一般解释,但对mukund所询问的JDBC问题并没有真正帮助. (4认同)

ger*_*tan 5

虽然我没有明确的解决方案,但似乎是应用服务器和数据库之间存在干扰通信.以下是您可以尝试隔离问题的一些事项:

  • 试着确定这是mysql问题还是java代码问题.尝试使用与应用服务器相同的主机上的命令行工具连接到mysql,并发出类似的SQL来执行登录.使用一个简单的java代码进行测试,该代码执行select,将其部署到同一个基础架构,查看发生的情况等.还要检查mysql服务器日志,看看是否可以找到任何有用的东西

  • 空闲连接有两种方式关闭:通过在app服务器内运行的连接池代码,或由mysql本身运行.确保检查双方的配置

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

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

祝好运