1. java
  2. android
  3. c#
  4. .net
  5. javascript
  6. php
  7. jquery
  8. html
  9. sql

Pool de conexões em uma aplicação Servlet

Boa tarde a todos,

Eu tenho uma mais de arquitetura do que um problema em si acredito eu. Eu tenho uma pequena aplicação Servlet que realiza a geração de alguns relatórios e gera a emissão de boletos e faturas para um portal de clientes. A questão é a seguinte: ultimamente o pessoal que cuida do Datacenter onde esta aplicação está começou a reclamar que o Oracle está gerando diversas críticas em relação a muitas conexões abertas, chegando a passar de 850 conexões abertas em dados momentos, o que está me fazendo rever toda arquitetura da aplicação.

Recentemente eu implementei um Pool de conexões com o DBCP na aplicação, porém não sei dizer se está implementado da maneira correta, pois segui alguns tutoriais para implementar, pois não tenho muito conhecimento nisso.

Eu sobreescrevi o método init() da Servlet para na primeira execução carregar as configurações do banco de dados e criar o Pool. o Pool é criado com as seguintes configurações no método init():

            dataSource = new BasicDataSource();
            dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
            dataSource.setUsername(usuario);
            dataSource.setPassword(senha);
            dataSource.setUrl(databaseURL);
            dataSource.setInitialSize(1);
            dataSource.setMinIdle(1);

O método init() chama um método estático de uma classe que vai criar o Pool, e após configurado tenho um método estático que irá retornar as conexões do Pool:

vConn = dataSource.getConnection();

Todos os métodos em que eu chamo o método para retornar a conexão possuem um bloco finally para encerrar a mesma:

vConn.close();

Tudo funciona perfeitamente em ambiente de homologação. Alguém poderia me dar uma luz se essa estrutura está correta, ou o que poderia estar deixando tantas conexões abertas no Oracle. Se alguém tiver experiência em realizar a configuração do Pool e puder me dar uma luz eu agradeço. Obrigado.

@Edit

Método que retorna as conexões:

public final class ConnectionFactory {   
    private static String usuario;
    private static String senha;
    private static String servidor;
    private static String porta;
    private static String servico;
    private static String databaseURL;
    private static Boolean gExecuta = true;

    private static BasicDataSource dataSource;

    public synchronized static void inicializaConexao(String pNomeAplicacao){
        if(gExecuta){
            StringBuilder vPath = new StringBuilder();
            Properties properties = new Properties();

            vPath.append(Constantes.DIR_CATALINA);
            vPath.append(Constantes.SEPARADOR_ARQUIVO);
            vPath.append("webapps");
            vPath.append(Constantes.SEPARADOR_ARQUIVO);
            vPath.append("config");
            vPath.append(Constantes.SEPARADOR_ARQUIVO);
            vPath.append(pNomeAplicacao);
            vPath.append(Constantes.SEPARADOR_ARQUIVO);
            vPath.append("banco.props");

            try{
                FileInputStream is = new FileInputStream(new File(vPath.toString()));
                System.out.println("==> Arquivo banco.props localizado em: " + vPath);
                properties.load(is);
            }catch (Exception e) {
                System.err.println("Arquivo de Propriedades não encontrado:" + e.getMessage());
            }

            usuario     = properties.getProperty("USUARIO");
            senha       = properties.getProperty("SENHA");
            servidor    = properties.getProperty("SERVIDOR");
            porta       = properties.getProperty("PORTA");
            servico     = properties.getProperty("SERVICO");

            databaseURL = "jdbc:oracle:thin:@" + servidor + ":" + porta + ":" + servico;

            dataSource = new BasicDataSource();
            dataSource.setDriverClassName("oracle.jdbc.driver.OracleDriver");
            dataSource.setUsername(usuario);
            dataSource.setPassword(senha);
            dataSource.setUrl(databaseURL);
          dataSource.setInitialSize(1);
            dataSource.setMinIdle(1)
            dataSource.setRemoveAbandoned(true);

            gExecuta = false;
        }        
    }

    public synchronized static Connection getConnection() throws SQLException{        
        Connection conn = null;
        try {
            conn = dataSource.getConnection();
        } catch (SQLException ex) {
            if(ex.getLocalizedMessage().contains("Violação de protocolo")){
                throw new SQLException("Erro na Conexão com o Banco de Dados. A senha do banco de dados está próxima de expirar.",ex);
            }else{
                throw new SQLException("Erro na Conexão com o Banco de Dados " + ex.getLocalizedMessage() ,ex);
            }
        }

        return conn;
    }       
}
  • Acredito que sobrescrever o método init() não resolverá o seu problema @BrunoAndradeSA. A ideia do pool de conexões é ter um min. e um máx. de conexões pré-estabelecidas com o SGBD antes de invocar o servlet. Você está utilizando algum container, como por exemplo Tomcat, para a sua aplicação?

    rogerio_gentil   14 de set de 2015
  • Eu uso o Tomcat como container, eu imaginei que por declarar o datasource como static todas as instâncias da Servlet compartilhariam ele.

    BrunoAndradeSA   15 de set de 2015
  • Pelo contrário @BrunoAndradeSA. Quando você faz uma chamada a um método estático, você está utilizando um recurso da classe, não da instância. Um método estático pode ser chamado sem que o objeto esteja criado. O problema neste caso é que você sobrescreveu o método init(), que é o primeiro método invocado quando o objeto é criado. Eu acho que sempre que você chamar o servlet, se o objeto não estiver na memória ele será recriado, recriando o pool de conexões.

    rogerio_gentil   15 de set de 2015
  • Rogério, primeiramente grato pela atenção desde já. Editei minha pergunta e adicionei minha classe que retorna a conexão do datasource. O método que é chamado pelo método init() da Servlet é inicializaConexao, omiti os métodos que fecham a conexão apenas. Nos meus métodos DAO, quando preciso de uma conexão chamo o método getConnection(). Note que é algo bem simples pois a aplicação é bem pequena, é mais como se fosse um módulo de outra aplicação.

    BrunoAndradeSA   15 de set de 2015
  1. Você vai ver essas setas em qualquer página de pergunta. Com elas, você pode dizer se uma pergunta ou uma resposta foram relevantes ou não.
  2. Edite sua pergunta ou resposta caso queira alterar ou adicionar detalhes.
  3. Caso haja alguma dúvida sobre a pergunta, adicione um comentário. O espaço de respostas deve ser utilizado apenas para responder a pergunta.
  4. Se o autor da pergunta marcar uma resposta como solucionada, esta marca aparecerá.
  5. Clique aqui para mais detalhes sobre o funcionamento do GUJ!

2 respostas

Não é a resposta que estava procurando? Procure outras perguntas com as tags oracle servlets java ou faça a sua própria pergunta.