Na primeira parte deste artigo, aprendemos a como estar melhorando o desempenho das nossas aplicações, substituindo o Tomcat pelo Undertow, que é um servidor web de alta performance, além de habilitar e configurar a compressão de dados, para reduzir o tamanho das respostas HTTP que trafegam pela rede.
Agora, iremos falar sobre como melhorar o desempenho de aplicação Spring Boot na parte de persistência, mas antes precisamos entender o que é JPA, Hibernate e Hikari.
JPA
JPA ou Java Persistence API, que posteriormente foi renomeada para Jakarta Persistence, é um padrão da linguagem Java que descreve uma interface comum para frameworks de persistência de dados.
A especificação JPA define o mapeamento relacional de objetos internamente, em vez de depender das implementações de mapeamento específicas do fornecedor.
Hibernate
O Hibernate é um dos frameworks de ORM que faz a implementação concreta da especificação JPA, ou seja, se nessa especificação é descrito que é preciso de métodos para persistir, remover, atualizar e buscar dados, quem vai de fato construir esses comportamentos é o Hibernate, assim como o EclipseLink, que é outro ORM.
Hikari
Hikari é um framework de connection pooling, que é responsável pelo gerenciamento de conexões com o banco de dados, mantendo-as abertas para que possam ser reutilizadas, ou seja, é um cache de conexões para solicitações futuras, tornando o acesso ao banco de dados mais rápido e reduzindo o número de novas conexões a serem criadas.
Configurando Hikari, JPA e o Hibernate
Uma configuração que podemos estar realizando para melhorar o desempenho é a seguinte:
Usando application.yml
:
spring:
hikari:
auto-commit: false
connection-timeout: 250
max-lifetime: 600000
maximum-pool-size: 20
minimum-idle: 10
pool-name: master
jpa:
open-in-view: false
show-sql: true
hibernate:
ddl-auto: none
properties:
hibernate.connection.provider_disables_autocommit: true
hibernate.generate_statistics: true
Usando application.properties
:
spring.datasource.hikari.auto-commit=false
spring.datasource.hikari.connection-timeout=50
spring.datasource.hikari.max-lifetime=600000
spring.datasource.hikari.maximum-pool-size=20
spring.datasource.hikari.minimum-idle=10
spring.datasource.hikari.pool-name=master
spring.datasource.jpa.open-in-view=false
spring.datasource.jpa.show-sql=true
spring.datasource.jpa.hibernate.ddl-auto=none
spring.jpa.properties.hibernate.generate_statistics=true
spring.jpa.properties.hibernate.connection.provider_disables_autocommit=true
Agora vamos a um breve um resumo das opções:
Hikari
spring.datasource.hikari.auto-commit
: Se forfalse
, toda conexão que for retornada pelo connection pool virá com auto-commit desabilitado.spring.datasource.hikari.connection-timeout
: Tempo, em milissegundos, que o cliente aguardará por uma conexão do pool. É preferível configurar um tempo curto para falhar rapidamente e retornar uma mensagem de erro, em vez de manter o cliente esperando indefinidamente.spring.datasource.hikari.max-lifetime
: Tempo máximo que uma conexão pode permanecer ativa. Configurar esse parâmetro é crucial para evitar falhas por conexões problemáticas e aumentar a segurança, já que conexões ativas por muito tempo são mais vulneráveis a ataques.-
spring.datasource.hikari.maximum-pool-size
: Tamanho máximo do pool, incluindo conexões ociosas e em uso, determinando o número máximo de conexões ativas com o banco de dados. Se o pool atingir esse limite e não houver conexões ociosas, chamadas para getConnection() serão bloqueadas por até connectionTimeout milissegundos antes de falharem.- Encontrar um valor adequado é importante, pois muitas pessoas acham que vão ter um ótimo desempenho definindo 50, 70 ou até 100. O ideal é ter 20 no máximo, que é a quantidade de threads em paralelo utilizando as conexões.
- Quanto maior o valor, mais difícil vai ser para banco de dados gerenciar essas conexões e muito provavelmente não conseguiremos ter throughput suficiente para utilizar todas essas conexões.
- É importante entender que do ponto de vista do RDBMS (Relational Database Management System) é difícil manter uma conexão aberta com ele mesmo, imagine n quantidade de conexões.
spring.datasource.hikari.minimum-idle
: Número mínimo de conexões que o pool mantém quando a demanda é baixa. O pool pode reduzir as conexões até 10 e recriá-las conforme necessário. No entanto, para desempenho máximo e melhor resposta a picos de demanda, é recomendado não definir esse valor, permitindo que o Hikari funcione como um pool de tamanho fixo. Padrão: igual aospring.datasource.hikari.maximum-pool-size
.spring.datasource.hikari.pool-name
: Nome definido pelo usuário para o pool de conexão e aparece principalmente em consoles de gerenciamento de registro e JMX para identificar pools e suas configurações.
JPA
spring.datasource.jpa.open-in-view
: Quando o OSIV (Open Session In View) está ativado, uma sessão é mantida durante toda a requisição, mesmo sem a anotação@Transactional
. Isso pode causar problemas de desempenho, como a falta de respostas da aplicação, pois a sessão mantém a conexão com o banco de dados até o fim da requisição.spring.datasource.jpa.show-sql
: Exibe ologging
do SQL que está sendo executado em nossa aplicação. Geralmente deixamos ativado em desenvolvimento, mas desativado em produção.-
spring.datasource.jpa.hibernate.ddl-auto
: Configura o comportamento do Hibernate em relação ao schema do banco de dados. Ela pode ter os seguintes valores:-
none
: Não faz nada. Gerenciamos manualmente o schema do banco. -
validate
: Valida o schema do banco de dados, mas não faz alterações. Isso é útil para garantir que o schema atual esteja de acordo com as entidades que mapeamos. -
update
: Atualiza o schema do banco de dados para refletir mudanças nas entidades. -
create
: Cria o schema do banco de dados. Se o schema já existir, ele vai remover e criar novamente. -
create-drop
: Cria o schema do banco de dados e, ao finalizar a aplicação, remove o schema. Útil para testes, onde desejamos um banco de dados limpo a cada teste.
-
spring.jpa.properties.hibernate.generate_statistics
: Serve para coletar informações detalhadas sobre o Hibernate, como tempos de execução de consultas, número de consultas executadas, e outras métricas.spring.jpa.properties.hibernate.connection.provider_disables_autocommit
: Informa ao Hibernate que desabilitamos o auto-commit dos providers (PostgreSQL, MySQL, etc). Isso impacta no desempenho, porque o Hibernate precisará obter uma conexão do pool para saber se o auto-commit está ou não está habilitado, para toda transação que ele fizer.
Com isso, fechamos a segunda parte do artigo. Nem todas as configurações presentes foram sobre desempenho, mas as que realmente impactam são as configurações do Hikari como auto-commit e pool size, as do JPA e Hibernate como OSIV (Open Session In View) e informar que desabilitamos o auto-commit dos providers.
Na próxima parte vamos falar sobre exceções e como elas podem ser configuradas, para poupar recursos da JVM (Java Virtual Machine).
Referências:
- https://en.wikipedia.org/wiki/Jakarta_Persistence
- https://www.ibm.com/docs/pt-br/was/8.5.5?topic=SSEQTP_8.5.5/com.ibm.websphere.nd.multiplatform.doc/ae/cejb_persistence.htm
- https://github.com/brettwooldridge/HikariCP
- https://github.com/corona-warn-app/cwa-server/issues/556
- https://medium.com/@rafaelralf90/open-session-in-view-is-evil-fd9a21645f8e
Top comments (0)