Melhores Práticas de desenvolvimento - Pool de Conexões

Olá pessoal!

Estou engajado em um projeto e preciso ter essa ideia muito bem definida e queria a ajuda de vocês.
Tenho, antes de tudo, que elaborar um seminário juntamente com os desenvolvedores e explicar quais são as melhores práticas de desenvolvimento e mostrá-los como devem proceder, bem como o ganho que terão com isso.
Por outro lado, irei estar incorporando ao projeto um Pool de Conexões para facilitar a programação e evitar a utilização desnecessária de conexões.

Aí vem a dúvida, como eu poderia estar criando um Pool de conexões de maneira “elegante” e que funcione. Ou seja, como posso elaborar ou utilizar de algum framework, abstração, container, ou seja lá o que for, a ideia de um pool de conexões e que este seja de fácil utilização e de configuração?

O maior medo é que os desenvolvedores fiquem com a responsabilidade de criar e fechar as conexões por conta própria, deixando arriscado a possibilidade de se deixar as conexões abertas e isso vir a ser um grande problema posteriormente.

De antemão, pensei em criar um filtro e fazer com que este faça uma conexão sempre que for necessário, claro, e executar o commit e / ou fechar a conexão sempre que estão não for mais necessária.

Enfim, essas são algumas dúvidas que espero que me ajudem para melhor definir o processo de desenvolvimento na elaboração deste projeto.

P.S.: Não sabia onde criar este post. Então criei aqui mesmo. Se estiver errado, por favor moderadores, mova-o para o local apropriado.

Abraços.

Olá,

Se você estiver usando algum mecanismo de persistência do banco de dados, como o Hibernate, você pode facilmente integrá-lo ao C3P0 que é um mecanismo de pool de conexões. Ficaria fácil como adicionar alguns parâmetros a seu hibernate.cfg.xml

Caso você não utilize um mecanismo assim, sugiro que você dê uma lida mais aprofundada no C3P0, mas continuo recomendando-o como pool de conexões.

Aqui encontrei algumas infos interessantes a respeito http://www.mchange.com/projects/c3p0/index.html

Dê uma lida, acredito que isso vá ajudar.

Abs,

Fábio, vou postar aqui alguma experiencia que tive com pool de conexoes e abertura e fechamento de conexao e transacao, espero que te ajude.

em um projeto, estava desenvolvendo utilizando o tomcat como container e utilizei o hibernate como orm, então aproveitei para criar o pool de conexoes com o c3p0 e implementei um filtro que abria e fechava a conexao a cada request, caso acontecesse uma exceçao ele fazia um rollback. Muita gente nao gosta desta abordagem por pegar uma conexao do pool e abrir uma transacao desnecessaria caso o request seja apenas um request de navegaçao, onde nao necessite nenhum recurso do db. Porem no meu caso isso nao criaria um gargalo no sistema, entao optei pela simplicidade.

em um outro projeto utilizando o glassfish, criamos o pool e o datasource no proprio servidor de aplicação, neste caso utilizamos o toplink como orm e EJBs, nao tenho muita experiencia em EJBs mas fui orientado que utilizando tal tecnologia nao seria necessario a abertura e fechamento de transacoes, entao neste caso ficamos livres de tal controle.

abrasssss

[quote=renanreismartins]Fábio, vou postar aqui alguma experiencia que tive com pool de conexoes e abertura e fechamento de conexao e transacao, espero que te ajude.

em um projeto, estava desenvolvendo utilizando o tomcat como container e utilizei o hibernate como orm, então aproveitei para criar o pool de conexoes com o c3p0 e implementei um filtro que abria e fechava a conexao a cada request, caso acontecesse uma exceçao ele fazia um rollback. Muita gente nao gosta desta abordagem por pegar uma conexao do pool e abrir uma transacao desnecessaria caso o request seja apenas um request de navegaçao, onde nao necessite nenhum recurso do db. Porem no meu caso isso nao criaria um gargalo no sistema, entao optei pela simplicidade.

em um outro projeto utilizando o glassfish, criamos o pool e o datasource no proprio servidor de aplicação, neste caso utilizamos o toplink como orm e EJBs, nao tenho muita experiencia em EJBs mas fui orientado que utilizando tal tecnologia nao seria necessario a abertura e fechamento de transacoes, entao neste caso ficamos livres de tal controle.

abrasssss[/quote]

eu nao entendi o porque de voce fazer um filtro para ficar fechando as conexoes. o pool jah se encarrega disso para voce. Na configuracao do pool voce define quantas conexoes voce quer manter ativas (maximo, minimo, etc), nao eh muito bom voce deixar o pool sempre vazio (tem como fazer isso tambem somente configurando o pool), mas ae voce vai ter um overhead, para abrir uma conexao nova a cada nova consulta, mantendo algumas conexoes abertas quando uma nova consulta eh executada o pool se encarrege de utilizar aquela conexao para executar sua query e depois libera a conexao sem precisar fecha-la

opa rollei, acho que me expressei mal, nao é exatamente para fechar, mas para devolver ao pool. como vc mesmo citou sempre deixo um numero min de conexoes ativas no pool. “retiro para uso, mas depois libero”

abrasss

Se voce estiver utilizando o padrao JPA(com hibernate) voce vai precisar apenas adicionar essa propiedade no persistence.xml (caso voce esteja usando hibernate sem JPA o arquivo eh o hibernate.cfg.xml)

            <!-- O Hibernate usa a propriedade hibernate.c3p0.max_size para
                 determinar se o C3P0 está sendo usado. As configurações colocadas
                 no arquivo c3p0.properties irão sobrescrever as setadas neste
                 arquivo -->
            <property name="hibernate.c3p0.max_size" value="10"/>

e depois adicionar um arquivo c3p0.properties na raiz do seu source (estando na raiz o c3p0 jah encontra o arquivo automaticamente)

### *****************************
### **** Propriedades do C3P0 ***
### *****************************

# Número de conexõs que o pool tentará adiquirur durante a inicialização. Deve
# ser um número entre  minPoolSize e maxPoolSize.
c3p0.initialPoolSize=5

# Número mínimo de conexões que o pool irá manter.
c3p0.minPoolSize=5

# Número máximo de conexões que o pool irá manter.
c3p0.maxPoolSize=15

# Segundos que uma Conexão será mantida no pool sem ser usada, antes de ser
# descartada. Zero significa que a conexão nunca expira.
c3p0.maxIdleTime=60

# O tamanho do cache do C3P0 para PreparedStatements. Se o valor de ambos, maxStatements
# e maxStatementsPerConnection, é zero, o cache será desabilitado. Se
# maxStatements é zero mas maxStatementsPerConnection é um valor diferente de
# zero, o cache será habilitado, mas sem um limite global, apenas com um limite
# por conexão. maxStatements controla o número total de Statements dos quais é
# feito cache, para todas as conexões. Se setado, deve ser um valor relativamente
# alto, já que cada Conexão do pool terá um determinado número de statements
# colocado em cache. Como um exemplo, considere quantos PreparedStatements
# distintos são frequentemente usados na sua aplicação e multiplique esse
# número por maxPoolSize para chegar num valor apropriado. Apesar do parâmetro
# maxStatements ser o padrão para o JDBC controlar o cache de statements, usuários
# podem achar mais intuitivo o uso do parâmetro maxStatementsPerConnection.
c3p0.maxStatements=0

# O número de PreparedStatements que o c3p0 irá colocar em cache, para cada conexão
# do pool. Se ambos maxStatements e maxStatementsPerConnection são zero, o cache
# de consultas ficará inativo. Se maxStatementsPerConnection é zero, mas maxStatements
# é um valor não nulo, o cache de consultas será habilitado, e um limite global
# imposto, mas por outro lado, não existirá nenhum limite individual por conexão.
# Se setado, maxStatementsPerConnection deveria ser um valor, aproximado, do número
# de PreparedStatements, distintos, que são frequentemente usados na sua aplicação
# mais dois ou três, para que as consultas menos comuns não tirem as mais comuns
# do cache. Apesar de maxStatements ser o parâmetro padrão em JDBC para controlar
# o cache de consultas, o usuário pode achar mais intuitivo usar o parâmetro
# maxStatementsPerConnection.
c3p0.maxStatementsPerConnection=10

# Determina quantas conexões por vez o c3p0 tenta adquirir quando o pool não tem
# conexões inativas para serem usadas.
c3p0.acquireIncrement=1

# Se idleConnectionTestPeriod é um número maior que zero, c3p0 irá testar todas
# as conexões inativas, que estão no pool e não fizeram o check-out, de X em X
# segundos, onde X é o valor de idleConnectionTestPeriod.
c3p0.idleConnectionTestPeriod=60

# O número de milisegundos que um cliente chamando getConnection() irá esperar
# por uma Conexão, via check-in ou uma nova conexão adquirida quando o pool estiver
# esgotado. Zero siginifica esperar indefinidademento. Setar qualquer valor positivo
# causará um time-out com uma SQLException depois de passada a quantidade especificada
# de milisegundos.
c3p0.checkoutTimeout=5000

# Tempo em milisegundos que o c3p0 irá esperar entre tentivas de aquisição.
c3p0.acquireRetryDelay=1000

# Define quantas vezes o c3p0 tentará adquirir uma nova Conexão da base de dados
# antes de desistir. Se esse valor é menor ou igual a zero, c3p0 tentará adquirir
# uma nova conexão indefinidamente.
c3p0.acquireRetryAttempts=5

# Se true, um pooled DataSource declarará a si mesmo quebrado e ficará permanentemente
# fechado caso não se consiga uma Conexão do banco depois de tentar acquireRetryAttempts
# vezes. Se falso, o fracasso para obter uma Conexão jogará uma exceção, porém
# o DataSource permanecerá valido, e tentará adquirir novamente, seguindo uma nova
# chamada para getConnection().
c3p0.breakAfterAcquireFailure=false

# Número de segundos que conexões acima do limite minPoolSize deverão permanecer
# inativas no pool antes de serem fechadas. Destinado para aplicações que desejam
# reduzir agressivamente o número de conexões abertas, diminuindo o pool novamente
# para minPoolSize, se, seguindo um pico, o nível de load diminui e Conexões não
# são mais requeridas. Se maxIdleTime está definido, maxIdleTimeExcessConnections
# deverá ser um valor menor para que o parâmetro tenho efeito. Zero significa que
# não existirá nenhuma imposição, Conexões em excesso não serão mais fechadas.
c3p0.maxIdleTimeExcessConnections=30

# c3p0 é muito assíncrono. Operações JDBC lentas geralmente são executadas por
# helper threads que não detém travas de fechamento. Separar essas operações atravéz
# de múltiplas threads pode melhorar significativamente a performace, permitindo
# que várias operações sejam executadas ao mesmo tempo.
c3p0.numHelperThreads=3

# Se true, e se unreturnedConnectionTimeout está definido com um valor positivo,
# então o pool capturará a stack trace (via uma exceção) de todos os checkouts
# de Conexões, e o stack trace será impresso quando o checkout de Conexões der
# timeout. Este paramêtro é destinado para debug de aplicações com leak de
# Conexões, isto é, aplicações que ocasionalmente falham na liberação/fechamento
# de Conexões, ocasionando o crescimento do pool, e eventualmente na sua exaustão
# (quando o pool atinge maxPoolSize com todas as suas conexões em uso e perdidas).
# Este paramêtro deveria ser setado apenas para debugar a aplicação, já que capturar
# o stack trace deixa mais o lento o precesso de check-out de Conexões.
c3p0.debugUnreturnedConnectionStackTraces=false

# Segundos. Se setado, quando uma aplicação realiza o check-out e falha na realização
# do check-in [i.e. close()] de um Conexão, dentro de período de tempo especificado,
# o pool irá, sem cerimonias, destruir a conexão [i.e. destroy()]. Isto permite
# que aplicações com ocasionais leaks de conexão sobrevivam, ao invéz de exaurir
# o pool. E Isto é uma pena. Zero significa sem timeout, aplicações deveriam fechar
# suas próprias Conexões. Obviamente, se um valor positivo é definido, este valor
# deve ser maior que o maior valor que uma conexão deveria permanecer em uso. Caso
# contrário, o pool irá ocasionalmente matar conexões ativas, o que é ruim. Isto
# basicamente é uma péssima idéia, porém é uma funcionalidade pedida com frequência.
# Consertem suas aplicações para que não vazem Conexões!!! Use esta funcionalidade
# temporariamente em combinação com  debugUnreturnedConnectionStackTraces para
# descobrir onde as conexões esão vazando!
c3p0.unreturnedConnectionTimeout=0

*** EDIT ***
Soh lembrando que voce tem alterar esses valores de configuracao para melhor se adequar a sua aplicacao

Eu recomendo voce usar Hibernate seguindo o JPA, eu particularmente acho um saco ficar alterando os xml dos pojos, pelo menos para mim parece bem mais natural manter as informacoes de mapeamento junto com a classe e nao em um arquivo externo.

n eh necessario utilizar jpa para colocar o mapeamento junto da classe

abrasss

BOM DIA! Apesar de eu ter clicado no botão “RESPONDER” na verdade só gostaria de clarear quanto a 1 pequena dúvida.

Em uma secretaria da prefeitura, temos um WebServer TOMCAT, nele configurei o POOL e funcionou corretamente em várias aplicações vRaptor, e um esquema no DB Oracle. Perfeito.

Porém, 1 aplicação específica, usa outro esquema no mesmo DB server.

Vamos lá … Do geito que está, conforme segue, funciona somente para um esquema, porém gostaríamos de acrescentar mais uma conexão para outro esquema:

NA APLICAÇÃO: classe ConnectionFactory: método:

public static Connection getConexaoOracleXE()throws Exception,SQLException{ Context initContext = new InitialContext(); Context envContext = (Context)initContext.lookup("java:/comp/env"); DataSource ds = (DataSource)envContext.lookup("jdbc/dbteste"); return ds.getConnection(); }

WEB SERVER TomCat: context.xml

[code]

<Resource name="jdbc/dbteste" auth="Container" minPoolSize="4"
	maxPoolSize="12" inactiveConnectionTimeout="20" removeAbandoned="true"
	maxActive="12" maxIdle="8" maxWait="-1" validateConnectionOnBorrow="true"
	type="javax.sql.DataSource" driverClassName="oracle.jdbc.OracleDriver"
	url="jdbc:oracle:thin:@192.168.0.10:1522:dbteste" username="login"
	password="senha" />

[/code]

WEB SERVER TomCat: web.xml

[code]

<resource-ref>
	<description>DB Connection</description>
	<res-ref-name>jdbc/dbteste</res-ref-name>
	<res-type>javax.sql.DataSource</res-type>
	<res-auth>Container</res-auth>
</resource-ref>

[/code]

Por que não criou um tópico em vez de desenterrar um sem necessidade alguma?

1 curtida