2. Agenda
● Problemas
● O que foi feito?
● Comportamento da solução aplicada
● Impactos
● Mudanças necessárias por parte dos desenvolvedores
● Status atual
● Dúvidas?
3. Problemas
● Pool de conexões
○ Estouro do pool
■ Muitas conexões sendo requisitadas ao mesmo tempo, onde, toda a quantidade disponível no
pool é utilizada
○ Lentidão
■ Quando o pool esta com todas as conexões disponíveis ocupadas, as novas requisições irão
ficar a espera de que alguma conexão seja liberada
○ Travamento dos sistemas
■ O pool não possui mais conexões disponíveis, o sistema permanece tentando obter conexões,
já com uma grande quantidade de requisições em espera por conexões, o sistema começa a
falhar, não retornando resposta aos usuários e por sua vez travando o servidor de aplicação
4. O que foi feito?
● Mais de 5 abordagens diferentes
○ Tentativa (testes de carga) e Erro (travamento dos sistemas, não devolução do recurso)
● Criação de um Holder (DatabaseResourcesHolder)
○ Controlar conexões
○ Controlar sessões do hibernate
○ Fechamento dos recursos (conexões e sessões do hibernate)
■ ViewFilter
■ MobileFilter
■ TarefaSchedule
● Connection Proxy para não permitir o fechamento das conexões fora do Holder
● A solução é perfeita?
○ Relatórios do Jasper/iReport abrindo conexões através de métodos Helper
5. Comportamento da solução aplicada
● Pool de 10 conexões no máximo
○ SIPAC
○ Comum
○ LogDB
● 15 threads sendo executadas
○ 4 usuários
● 20 iterações
○ 3 URL’s visitadas
■ /login/
■ /login.do
■ /telaInicial.do
9. Comportamento da solução aplicada
● Houve estouro do Pool?
○ Sim, o teste aplicado foi para este fim, fazer o pool trabalhar no limite, assim, sem possibilidade de
liberar conexões sempre que requisitado
● Houve lentidão?
○ Sim, no gráfico anterior reparamos que o pico máximo foi de 180.000 milissegundos (3 minutos),
mas, o sistema não deixou de responder e devolver recursos ao pool
● Houve travamento do sistema?
○ Não, em nenhum momento o sistema deixou de responder, mesmo com todos os recursos do pool
alocados, o sistema não chegou a travar e continuou respondendo e devolvendo os recursos não
mais utilizados ao pool
10. Comportamento da solução aplicada
● Então quais os benefícios?
○ Não houve travamento nos testes aplicados
○ Reaproveitamento das conexões com banco de dados
○ Reaproveitamento das sessões do Hibernate
○ “Garantimos” a devolução da conexão ao Pool de conexões
● Como podemos melhorar?
○ Otimizações de consultas
○ Uso correto de mapeamentos
○ Boas práticas no geral
11. Impactos
● Objetivos
○ Controle de abertura de conexões e sessões do hibernate
○ Melhoria no desempenho dos sistemas
○ “Garantia” de devolução do recurso (conexão) ao pool
● Consequências
○ Transação, Conexão e Sessão do Hibernate
○ Método ‘dao.refresh’ e ‘JdbcTemplate’
○ Mapeamentos SET no hibernate
○ Abertura de conexões em relatórios através de métodos *Helper
○ Métodos *NoFlush
12. Mudanças necessárias por parte dos desenvolvedores
● Entendimento melhor de cada escopo envolvido na camada de persistência
● Uso correto de mapeamentos do hibernate (Set/List)
● Uso adequado do método ‘dao.refresh’
○ Dentro de uma sessão do hibernate
○ Informação alterada com uso do “createSQLQuery”
● Identificar e corrigir relatórios que abrem conexões por métodos *Helper
○ Buscar métodos (get na maioria das vezes) nas coleções que são passadas aos relatórios que fazem
chamadas a métodos *Helper os quais abrem conexões com o banco de dados e executam consultas
● Utilização correta de métodos *NoFlush
○ Usar métodos ‘executeAndFlushClosingResources’
14. Uso adequado do método ‘dao.refresh’ e ‘JdbcTemplate’
● Há várias situações nos sistemas em que uma entidade possui informações
atualizadas via os métodos ‘update,’ ‘updateField’ e ‘updateFields’, os quais,
executam um procedimento SQL nativo para atualizar estas informações
diretamente no banco de dados.
15. Uso adequado do método ‘dao.refresh’ e ‘JdbcTemplate’
● Muitas das vezes o desenvolvedor acaba de atualizar estas informações e em
seguida as consulta usando o 'findByPrimaryKey', prática a qual, com as novas
modificações na arquitetura, devem gerar erros pois estas informações não serão
realmente consultadas ao banco de dados e sim a sessão do hibernate.
16. Uso adequado do método ‘dao.refresh’ e ‘JdbcTemplate’
● Então para corrigir estes casos, indica-se o uso do método 'refresh', o qual faz uma
atualização dos dados em sessão no hibernate em relação ao banco de dados,
assim trazendo a informação mais atual para a sessão.
17. Uso adequado do método ‘dao.refresh’ e ‘JdbcTemplate’
● Indica-se o uso do método 'findByPrimaryKey', quando for utilizado o
JdbcTemplate para sincronização dos dados em sessão no hibernate em relação ao
banco de dados, assim trazendo a informação mais atual para a sessão.
18. Uso adequado do método ‘dao.refresh’ e ‘JdbcTemplate’
● Isto é uma prática para resolver os casos apenas trocando o método, mas uma
melhor abordagem do código poderia resolver a situação e tornar o fluxo mais
eficiente.
● Qual o objetivo de consultar novamente no banco de dados uma informação que
conhecemos, esta a qual, acabamos de atualizar?
22. Uso correto de mapeamentos do hibernate (Set/List)
● Ao executar operações dentro de um processador(contexto transacional) o
hibernate força uma sincronização das entidades na Session, causando o
ClassCastException.
25. Uso correto de mapeamentos do hibernate (Set/List)
● Uso do Set (Interface) e suas Implementações
○ O Set quando instanciado como TreeSet não permite outra instanciação, apenas a primeira deve ser
mantida;
○ Nos casos em que as coleções devem ser limpas para receber novos valores então o programador
deve usar: set.clear(); set.addAll(new TreeSet<?>(Collection));
● Mapeamentos no Hibernate
○ Mapeamentos que usam <set> devem possuir seus atributos definidos como Set, Collection não
deve ser utilizado pois possibilita que o programador utilize a instancia de um ArrayList quando o
Hibernate espera que seja um Set;
26. Identificar e corrigir relatórios que abrem conexões por
métodos *Helper
● Existem situações onde coleções que possuem métodos de acesso a atributos
fazem chamadas a classes ‘Helpers’, onde muitas delas, fazem chamadas a classes
de acesso a dados ‘DAOs’, chamadas que na maioria das vezes abrem conexões
com o banco de dados para que a informação necessária seja retornada.
29. Identificar e corrigir relatórios que abrem conexões por
métodos *Helper
● Invocado no relatório HistoricoComponentesMatriculadosGraduacao.jasper.
30. Identificar e corrigir relatórios que abrem conexões por
métodos *Helper
● No caso acima, o relatório no Jasper receberia uma coleção de históricos, onde
estes, por sua vez, são iterados, e para cada histórico, sua coleção de
“matriculasDiscente” também é iterada, quando o valor de
“getComponenteHATotal()” for recuperado, este irá chamar um Helper, o qual
chamará uma DAO, que abrirá uma conexão com o banco de dados. Neste caso,
com as alterações feitas na arquitetura, esta conexão será aberta em uma thread a
qual não temos o controle, impossibilitando o fechamento desta conexão, assim,
possibilitando problemas com o pool de conexões.
31. Identificar e corrigir relatórios que abrem conexões por
métodos *Helper
● Para que este problema seja resolvido, é necessário que TODOS os dados os quais
o relatório necessite, sejam consultados antes do processamento do relatório, e
assim, a coleção de históricos enviada ao relatório já vá com todos os seus dados
populados. Estes casos exigem que, uma refatoração seja feita na consulta onde os
dados são populados, antes do processamento do relatório pelo Jasper.
32. Utilização correta de métodos *NoFlush
● Processamento de inserções e atualizações de N registros por vez (em “lote”)
● Otimização: commit feito no final do processamento com o método
GenericDAOImpl.close().
● Usar métodos ‘AbstractController.executeAndFlushClosingResources(...)’
37. Status atual
● Enviado ao TRUNK do SVN para avaliação dos desenvolvedores
● Recebendo feedbacks sobre problemas identificados
● Será enviada para produção com o SIGRH ou SIPAC
38. Dúvidas?
● https://goo.gl/WTZGAM (Wiki SINFO - Soluções em Metodologias e Arquitetura Tecnológica)
● Raphael Medeiros
○ Skype: raphael.j.medeiros
● André Rabelo
○ Skype: andre.rabelo.pereira
?