what is java.io.EOFException, Message: Não é possível ler a resposta do servidor. Espera-se que leia 4 bytes, leia 0 bytes

Esta pergunta foi feita algumas vezes em SO e muitas vezes em outros sites. Mas eu não recebi nenhuma resposta satisfatória.

Meu problema:
Eu tenho um aplicativo web java que usa JDBC simples para se conectar ao database mysql através do servidor de aplicativos Glassfish .

Eu usei pool de conexão no servidor glassfish com as seguintes configurações:
Tamanho inicial da piscina: 25
Tamanho Máximo da Piscina: 100
Quantidade de redimensionamento da piscina: 2
Tempo limite ocioso: 300 segundos
Tempo máximo de espera: 60.000 milissegundos

O aplicativo foi implantado nos últimos 3 meses e estava funcionando perfeitamente também.
Mas dos últimos 2 dias o seguinte erro está chegando no momento do login.

StackTrace Parcial

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

O que causou esse erro de repente? Eu perdi muito tempo para isso.

EDIT: O problema ainda persiste após reiniciar o servidor. De acordo com o DBA, duas das configurações importantes do servidor mysql são:
wait_timeout: 1800 segundos
connect_timeout: 10 segundos
NOTA: Outros aplicativos implantados no mesmo servidor que se conectam ao mesmo database e usam pools diferentes estão sendo executados sem problemas.

EDIT-2: Depois de ler muitas coisas e esperar algum resultado positivo, fiz essas alterações no meu pool de conexão.

Tempo máximo de espera: 0 (anteriormente eram 60 segundos)
Validação de Conexão: Obrigatório
Método de validação: tabela
Nome da Tabela: Demo
Validar Atmost Once: 40 segundos
Tentativas de repetição de criação: 1
Repetir Intervalos: 5 segundos
Uso Máximo de Conexão: 5

E isso funcionou como o aplicativo está sendo executado por 3 dias de forma consistente. Mas eu tenho um resultado muito estranho e interessante disso. Enquanto monitorava o pool de conexões, encontrei esses números:

NumConnAcquired: 44919 Contagem
NumConnReleased: 44919 Contagem
NumConnCreated: 9748 Contagem
NumConnDestroyed: 9793 Contagem
NumConnFailedValidation: contagem de 70
NumConnFree: 161 Contagem
NumConnUsed: -136 Contagem

Como o NumConnFree pode se tornar 161, pois eu tenho o Maximum Pool Size = 100 ?
Como o NumConnUsed pode se tornar -136, um número negativo ?
Como pode o NumConnDestroyed > NumConnCreated ?

A conexão falhou, possivelmente devido a um tempo limite ocioso do firewall, etc. Se você não tiver seu driver JDBC configurado para reconectar a falha, esse erro não desaparecerá, a menos que você abra uma nova conexão.

Se você estiver usando um pool de conexão de database (você está usando um, certo?), Provavelmente desejará ativar seus resources de verificação de conexão, como emitir uma consulta para verificar se a conexão está funcionando antes de devolvê-la ao aplicativo. No Apache commons-dbcp, isso é chamado de validationQuery e geralmente é definido como algo simples como o SELECT 1 .

Como você está usando o MySQL, você deve usar uma consulta “ping” específica do Connector / J que seja mais leve do que realmente emitir uma consulta SQL verdadeira e definir sua consulta de validação como /* ping */ SELECT 1 (as necessidades da parte ping para ser exato ).

Isso provavelmente significa que o database foi reiniciado ou que a conexão de rede com o database foi interrompida (por exemplo, uma conexão NAT expirou) … e seu webapp está tentando usar uma conexão de database obsoleta.

Se o problema persistir depois de reiniciar o contêiner da Web, poderá ser algo mais sério.


Você perguntou o seguinte:

 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 ? 

Em face disso, isso não faz sentido. No entanto, eles poderiam ser simplesmente o resultado de alguns contadores de uso serem atualizados de maneira não segura para thread. Isso não está necessariamente relacionado ao seu problema original.

Isso é EndOfFileException em java, acontece quando o ponto inicial do cursor está no ponto final ou quando a conexão com o database é fechada devido a alguma exceção inesperada.

Embora eu não tenha soluções definitivas, parece que algo está interferindo na comunicação entre o servidor de aplicativos e o database. A seguir, algumas coisas que você pode tentar isolar os problemas:

  • Tente determinar se este é problema mysql ou problema de código java. Tente conectar-se ao mysql usando a ferramenta de linha de comando do mesmo host que o servidor de aplicativos e emitir um SQL semelhante para executar o login. Teste usando um código java simples que faz um select, implemente-o na mesma infraestrutura, veja o que acontece etc. Também verifique o log do servidor mysql, veja se consegue encontrar alguma coisa útil

  • Há duas maneiras de fechar uma conexão inativa: pelo código do pool de conexão que é executado dentro do servidor de aplicativos ou pelo próprio mysql. Certifique-se de verificar a configuração em ambos os lados

  • Verifique se alguma configuração de infraestrutura de rede foi alterada recentemente. Havia alguma nova regra de firewall interferindo na conectividade <-> mysql do servidor de aplicativos? Houve alguma configuração que proíba a conexão TCP aberta em espera por mais de X?

  • Tente uma biblioteca de pool de conexão diferente apenas para eliminar a possibilidade de que seja o pool de conexão

Boa sorte

Pode ser um problema relacionado ao Firewall.

Eu tive esse problema, mas eu não era possível fazer alterações na configuração do database MySQL. Por isso, assegurei que na minha class de conector sql a conexão é sempre fechada antes de ser iniciada novamente. Algo como:

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

E isso resolveu o problema.