Tentativa de conexão MySQL trava a Thread

Bom dia pessoal, como vão?

Estou com um problema no trabalho, que vou relatar e conto com possíveis dicas ou ajudas.

Tenho algumas aplicações J2EE rodando em um mesmo servidor Tomcat 5.5, e JDK 1.5. Uma destas aplicações se conecta à um BD MySQL em outra máquina (podem ser diversos - uns 25 - dependendo do usuário/máquina que faz o acesso), e tudo funciona quase perfeitamente bem.

O problema que está ocorrendo é que, muitas vezes, o computador onde está instalado o MySQL, está com firewall ativado. É uma diretriz nossa sempre liberar o acesso às portas do MySQL, porém nem sempre isso ocorre de imediato. Desta forma, quando o programa tenta conectar ao MySQL, ele fica aguardando (porque o firewall o trava), segurando então todas as outras aplicações.

Só que como tenho uns 600 usuários tentando acessar (novamente) as várias outras aplicações, com essa tentativa de conexão segurando a coisa, um monte de thread começa a subir até chegar no limite.

Sei que essa de ter várias aplicações rodando em um mesmo servidor web é complicado, mas é o que pode-se fazer atualmente.

Alguém tem alguma idéia a respeito dessa thread em específico do MySQL segurar todas as outras? Percebi que o método de connect é syncrhonized, mas terá algo a ver?

Vale lembrar que se eu mato essa thread, todas as outras são liberadas e o resto fica “acessível”, e resolvendo o problema do firewall, também evita o erro.

Agradeço desde já!

Você está usando um pool de conexões?
na minha experiencia, se o firewall trava o acesso, não deveria ficar aguardando, simplesmente daria um erro de conexão e a thread seria liberada.

[quote=furutani]Você está usando um pool de conexões?
na minha experiencia, se o firewall trava o acesso, não deveria ficar aguardando, simplesmente daria um erro de conexão e a thread seria liberada.[/quote]2

Obrigado pela avaliação senhores!

Este foi meu pensamento também. Porém, não sei porque cargas d’água demora muito para informar que a conexão não pode ser feita.

Ao tentar realizar a conexão com o referido banco, ali fica por uns 2 minutos aguardando resposta, segurando todas as outras aplicações (que nem usam MySQL). Afirmo que é o firewall, porque simplesmente quando desabilitamos, funciona.

Estou pensando em usar um filter específico para isso nessa aplicação, será que resolve? Senão, o jeito é sempre ir desabilitando firewalls.

não tenho tanta certeza quanto ao “se o firewall trava o acesso, não deveria ficar aguardando, simplesmente daria um erro de conexão e a thread seria liberada”… no pool do tomcat por exemplo que usa o DBCP, existe um parâmetro chamado maxWait que se refere ao tempo de espera para estabelecer uma conexão antes de lançar uma exceção por que não conseguiu a conexão… acredito que isso se encaixe no caso… como é feita essa conexão, é no pool do tomcat, no pool do c3p0 via hibernate, você cria a conexão jdbc na mão… ?

ah e a proposito, pelo que você descreveu isso é um problema que se refere ao firewall, quem costuma ser responsável por verificar isso é alguém de infraestrutura, administrador de rede, alguma coisa assim, não desenvolvedor… se o firewall está bloqueando o acesso da aplicação ao banco, esse é o problema, não é na aplicação.

Olá, esqueci de mencionar. A conexão é criada “na mão” mesmo:

try {
  Class.forName(driver);
  g.setConexao(DriverManager.getConnection(databaseURL,g.getDscUsuario(), g.getDscSenha()));
} catch (SQLException ex) {
  String mensagemDeErro = "Não foi possível completar a conexão com a base de dados.";
  throw new Exception(mensagemDeErro);
}

‘g’ é o objeto onde “armazeno” a conexão logo no inicio do sistema, que já vem preparada com os dados de URL, Usuário e Senha.

Concordo que o Firewall é problema de Infraestrutura. Porém, acho muito estranho ele segurar todas as minhas outras aplicações das outras estações, por causa de uma com firewall habilitado.
Vou dar uma olhada sobre o pool de conexões com DBCP, pode ser um ganho.

Obrigado novamente!

[quote=ticks.mas]Olá, esqueci de mencionar. A conexão é criada “na mão” mesmo:

try {
  Class.forName(driver);
  g.setConexao(DriverManager.getConnection(databaseURL,g.getDscUsuario(), g.getDscSenha()));
} catch (SQLException ex) {
  String mensagemDeErro = "Não foi possível completar a conexão com a base de dados.";
  throw new Exception(mensagemDeErro);
}

‘g’ é o objeto onde “armazeno” a conexão logo no inicio do sistema, que já vem preparada com os dados de URL, Usuário e Senha.

Concordo que o Firewall é problema de Infraestrutura. Porém, acho muito estranho ele segurar todas as minhas outras aplicações das outras estações, por causa de uma com firewall habilitado.
Vou dar uma olhada sobre o pool de conexões com DBCP, pode ser um ganho.

Obrigado novamente![/quote]

quanto ao firewall, a minha opinião é que ele deveria permitir conexão conexão na porta do banco a qualquer momento vindo do ip do servidor web. Acredito que isso funcione da mesma forma que um socket, enquanto está tentando conectar vai travar a thread a qual se encontra… se você quer uma resposta mais rápida quanto a se conseguiu ou não conectar, existe forma de setar isso: http://docs.oracle.com/javase/6/docs/api/java/sql/DriverManager.html#setLoginTimeout(int)

quanto a timeout, da uma olhada nesse link: http://www.roseindia.net/jdbc/Jdbc-connection-timeout.shtml

Obrigado pelas dicas! Vou tentar seguir esta linha de raciocínio!

Valeu!

Olá pessoal.

Apenas para explanar a solução que usei.

Segui a ideia de usar um timeout. Porém, me deparei com o problema de que o DriverManager.setTimeout não funciona para o MySQL.

O que fiz, foi tentar uma conexão comum de rede na porta 3306 no servidor MySQL, com timeout. Se não for possível conectar neste tempo, eu paro por ai e nem tento via DriverManager.

Abraços e obrigado pela ajuda.