1. Configurações Essenciais (server.xml)
O arquivo conf/server.xml contém as definições primárias do Tomcat e é o ponto de partida para ajustes de performance.
1.1 Gerenciamento de Threads (Executor)
O Tomcat utiliza um pool de threads para processar as requisições recebidas. A configuração adequada deste pool minimiza a sobrecarga de criação e destruição de threads, aumentando a capacidade de processamento simultâneo.
<Executor name="applicationExecutor"
namePrefix="app-request-"
maxThreads="250"
minSpareThreads="60"
maxIdleTime="30000"
queueCapacity="150"
prestartminSpareThreads="true"/>
Princípios de Ajuste:
maxThreads: Define o número máximo de threads. Um valor entre 150 e 400 é comum, dependendo da CPU e da natureza das requisições (CPU-bound vs. I/O-bound). Valores excessivamente altos podem aumentar o overhead de troca de contexto.minSpareThreads: Garante um número mínimo de threads prontas para uso, evitando atrasos em picos de requisições. Recomenda-se um valor superior à média de concorrência esperada.queueCapacity: A fila de espera para requisições quando todas as threads estão ocupadas. Um valor razoável evita que o servidor rejeite requisições, mas um valor muito grande pode levar a tempos de espera excessivos.maxIdleTime: Tempo em milissegundos que uma thread pode permanecer ociosa antes de ser terminada (se acima deminSpareThreads).
1.2 Otimização do Conector (Connector)
O Conector é responsável por receber e despachar as requisições dos clientes. A escolha do protocolo e seus parâmetros são vitais para a eficiência da conexão.
1.2.1 Seleção de Protocolo (Preferência por Modos Não Bloqueantes)
O Tomcat oferece diferentes protocolos, com performance crescente: BIO < NIO < NIO2 < APR. Recomenda-se NIO2 ou APR para ambientes de alta performance.
BIO(Blocking IO): Legado, inadequado para alta concorrência.NIO(Non-blocking IO): Protocolo padrão a partir do Tomcat 8, adequado para boa concorrência.NIO2(Asynchronous Non-blocking IO): Baseado em Java AIO, oferece melhor desempenho que NIO, ideal para conexões persistentes e assíncronas.APR(Apache Portable Runtime): A mais performática, utiliza bibliotecas nativas C. Exige instalação de componentes adicionais (APR e OpenSSL nativo).
Exemplo de Configuração (Protocolo NIO2):
<Connector executor="applicationExecutor"
port="8080"
protocol="org.apache.coyote.http11.Http11Nio2Protocol"
connectionTimeout="15000"
keepAliveTimeout="45000"
maxKeepAliveRequests="120"
compression="on"
compressionMinSize="1024"
compressableMimeType="text/html,text/xml,application/json,application/javascript,text/css,image/svg+xml"
redirectPort="8443"/>
1.2.2 Ajuste dos Parâmetros de Conexão
connectionTimeout: Tempo máximo em milissegundos para estabelecer uma conexão. Um valor entre 10-20 segundos é prudente para evitar que conexões incompletas prendam recursos.keepAliveTimeout: Tempo de inatividade antes de fechar uma conexão persistente. Ajuste conforme a necessidade da aplicação; 30-60 segundos é comum para APIs.maxKeepAliveRequests: Número máximo de requisições que uma conexão persistente pode servir. Limita o uso de recursos por uma única conexão.compression: Ative a compressão GZIP para reduzir o tamanho dos dados transferidos.compressionMinSize: Tamanho mínimo em bytes para aplicar a compressão.compressableMimeType: Tipos MIME que devem ser comprimidos.
1.3 Otimização de Host e Contexto
Reduzir a carga desnecessária é fundamental.
- Desabilitar funcionalidades não essenciais: Remova ou desabilite aplicações de gerenciamento como
managerehost-managerdo diretóriowebappsem ambientes de produção. - Configurar Caminhos de Contexto: Especifique
docBaseeworkDirpara evitar a descompactação desnecessária de WARs e garantir que o trabalho temporário seja armazenado em um local otimizado.
<Host name="mywebapp.com" appBase="webapps" unpackWARs="false" autoDeploy="false">
<Context path="/api" docBase="/srv/app/myapp-backend" workDir="/var/tomcat/work/api"/>
</Host>
unpackWARs="false": O Tomcat executará o WAR diretamente, economizando tempo e espaço em disco.
autoDeploy="false": Desabilita a deteccção e implantação automática de novas aplicações, crucial em produção para evitar instabilidades.
2. Otimização da JVM
Como o Tomcat opera dentro de uma JVM, a alocação de memória e a configuração do coletor de lixo (GC) são decisivas para a estabilidade e performance. Estas configurações são definidas via JAVA_OPTS nos scripts catalina.sh (Linux) ou catalina.bat (Windows).
2.1 Configuração de Memória (Heap e Metaspace)
# Memória Heap (área principal para objetos da aplicação)
-Xms3G # Tamanho inicial do heap (igual ao máximo para evitar redimensionamentos)
-Xmx3G # Tamanho máximo do heap (Ex: 3GB para servidor de 8GB RAM, deixando 5GB para SO/outros)
# Memória para Geração Jovem (New Generation)
-XX:NewSize=1.5G # Tamanho inicial da geração jovem
-XX:MaxNewSize=1.5G # Tamanho máximo da geração jovem (normalmente 1/2 ou 1/3 do heap total)
# Metaspace (para metadados de classes e métodos)
-XX:MetaspaceSize=384m # Tamanho inicial do Metaspace
-XX:MaxMetaspaceSize=768m # Tamanho máximo do Metaspace (evita OOM: Metaspace)
Diretrizes de Ajuste:
- Heap (
-Xms,-Xmx): Otimize para evitarOutOfMemoryErrore reduzir a frequência de GC. Um heap muito pequeno resulta em GC frequente; muito grande, em GC demorado. - Geração Jovem: Aplicações com muitos objetos de curta duração (como APIs REST) podem se baneficiar de uma geração jovem maior, reduzindo GCs na geração antiga.
2.2 Otimização do Coletor de Lixo (Garbage Collector)
A escolha do GC pode impactar significativamente a latência da aplicação (tempo de pausa "Stop-The-World" - STW).
| Cenário | Coletor de Lixo Recomendado | Configuração de JAVA_OPTS |
|---|---|---|
| Aplicações Moderadas (< 6GB) | G1GC (Padrão, balanceado) | -XX:+UseG1GC -XX:MaxGCPauseMillis=150 |
| Alta Latência, Grandes Heaps | ZGC (JDK 11+ / Muito Baixa Latência) | -XX:+UnlockExperimentalVMOptions -XX:+UseZGC -XX:ZGCHeapSizeLimit=10G |
| Alto Throughput | Parallel GC | -XX:+UseParallelGC -XX:+UseParallelOldGC |
Parâmetros Adicionais:
-XX:MaxGCPauseMillis: Define uma meta de tempo máximo de pausa para o G1GC.-XX:+DisableExplicitGC: Impede que chamadas programáticas comoSystem.gc()disparem Full GCs desnecessários.
3. Otimização da Arquitetura de Deployment
A escala horizontal e a delegação de tarefas podem aumentar drasticamente a capacidade do Tomcat.
3.1 Separação de Recursos Estáticos
Delegar o tratamento de arquivos estáticos (HTML, CSS, JS, imagens) a um servidor web mais eficiente como Nginx libera o Tomcat para processar requisições dinâmicas.
# Exemplo de configuração Nginx
server {
listen 80;
server_name www.myapp.com myapp.com;
# Servir arquivos estáticos diretamente
location ~* \.(css|js|gif|png|jpe?g|svg|woff2?|eot|ttf|ico)$ {
root /usr/share/nginx/html/static; # Caminho para os recursos estáticos
expires 30d; # Cache no navegador por 30 dias
add_header Cache-Control "public, no-transform";
}
# Encaminhar requisições dinâmicas para o Tomcat
location / {
proxy_pass http://localhost:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_read_timeout 90;
}
}
3.2 Clusterização e Balanceamento de Carga
Múltiplas instâncias do Tomcat, combinadas com um balanceador de carga, aumentam a disponibilidade e escalabilidade.
upstream backend_app_servers {
server 192.168.1.10:8080 weight=5; # Servidor primário, maior peso
server 192.168.1.11:8080 weight=3; # Servidor secundário
server 192.168.1.12:8080 backup; # Servidor de backup, usado se os outros falharem
# sticky; # Adicionar para persistência de sessão baseada em cookie, ou usar ip_hash
}
server {
listen 80;
server_name api.myapp.com;
location / {
proxy_pass http://backend_app_servers;
proxy_set_header Host $host;
# ... outros headers proxy ...
}
}
Para lidar com a persistência de sessão em um cluster, pode-se usar ip_hash no Nginx (menos flexível), ou uma solução mais robusta como um gerenciador de sessão externo (e.g., tomcat-redis-session-manager com Redis).
3.3 Habilitação do HTTP/2
O HTTP/2 oferece melhorias significativas de performance sobre o HTTP/1.1 (multiplexação, compressão de cabeçalhos). O Tomcat 8.5+ o suporta, exigindo SSL/TLS.
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Nio2Protocol"
SSLEnabled="true" scheme="https" secure="true"
sslProtocol="TLSv1.2+TLSv1.3"
keystoreFile="/etc/ssl/certs/myapp_cert.jks"
keystorePass="s3cur3p4ssw0rd"
keyAlias="app_alias"
http2="true"/>
4. Outras Otimizações e Boas Práticas
Alguns ajustes adicionais podem complementar as otimizações principais.
- Desabilitar Conecter AJP: Se você não estiver usando o Apache HTTP Server com o módulo
mod_jkoumod_proxy_ajp, o conector AJP pode ser removido deserver.xmlpara liberar recursos. - Configurar Cache do Navegador: Utilize cabeçalhos
Cache-ControleExpirespara recursos estáticos para reduzir requisições desnecessárias. Isso pode ser feito via Nginx (como mostrado acima) ou via filtros no próprio Tomcat. - Otimização do Código da Aplicação: A base da performance reside na eficiência do código Java. Evite operações demoradas em threads de requisição, use processamento assíncrono (com
AsyncContext) e minimize o volume de dados armazenados em sessão. - Limpeza Regular de Arquivos Temporários: Os diretórios
work(para JSPs compilados) etempdo Tomcat devem ser limpos periodicamente para evitar o acúmulo de arquivos que podem consumir espaço em disco e, em alguns casos, afetar a performance.
5. Monitoramento e Estratégias de Ajuste
A otimização é um processo contínuo, guiado por dados de monitoramento.
Ferramentas de Monitoramento:
- JVM:
jconsole,jvisualvm(para heap, GC, threads). - Tomcat: O status do Manager (
/manager/status) fornece métricas de threads e conexões. - Sistema:
top(CPU, memória),netstat(conexões de rede),iostat(I/O de disco).
Ciclo de Ajuste:
- Testes de Carga: Use ferramentas como JMeter ou k6 para simular cenários de alto tráfego e identificar gargalos (tempos de resposta altos, erros).
- Análise de Métricas: Examine os logs do Tomcat, logs de GC e as métricas das ferramentas de monitoramento.
- Otimização Direcionada: Ajuste os parâmetros específicos que se mostraram limitantes (e.g., aumentar
maxThreadsse o pool estiver esgotado, ou ajustar o heap da JVM se houver GCs frequentes). - Verificação: Repita os testes de carga para validar os ajustes e garantir que não houve introdução de novos problemas. O objetivo é equilibrar o uso de recursos com a performance.