Como Ajustar Timeouts e Keepalive no Apache e Nginx

13 min de leitura Infraestrutura
Como Ajustar Timeouts e Keepalive no Apache e Nginx

A configuração de timeouts e conexões persistentes (keepalive) é um dos ajustes mais impactantes para o desempenho de servidores web rodando em ambientes de Virtual Private Server (VPS). Muitos administradores focam exclusivamente na otimização do PHP ou do banco de dados, negligenciando a camada de transporte que conecta o cliente ao servidor. Em cenários de alta concorrência ou com usuários em conexões lentas, uma configuração inadequada pode resultar em timeouts prematuros, consumo excessivo de memória RAM devido a conexões zumbis e degradação significativa da experiência do usuário.

Neste tutorial, vamos detalhar como ajustar corretamente os parâmetros timeout e keepalive tanto no Apache quanto no Nginx em uma VPS Ubuntu. O objetivo é equilibrar a retenção de conexões ativas para aproveitar o reuso de TCP (evitando o overhead do handshake TLS e TCP) com a liberação rápida de recursos para novos solicitantes.

1. Conceitos Fundamentais: Timeout vs. Keepalive

Antes de aplicar as configurações, é crucial entender a diferença entre os dois conceitos, pois eles atuam em camadas diferentes do ciclo de vida da conexão HTTP.

O Keepalive permite que múltiplos requisições e respostas sejam transmitidas sobre uma única conexão TCP. Sem ele, o navegador precisaria estabelecer uma nova conexão TCP (e realizar o handshake TLS) para cada arquivo estático (CSS, JS, imagens). Isso reduz drasticamente a latência percebida pelo usuário.

O Timeout, por outro lado, define quanto tempo o servidor aguarda por uma nova requisição dentro de uma conexão keepalive aberta antes de fechá-la. Se um cliente abrir uma conexão e não enviar nada por 60 segundos, o servidor libera esse recurso. Definir esse valor muito alto pode levar ao acúmulo de milhares de conexões ociosas, esgotando a tabela de sockets do sistema operacional.

A otimização consiste em encontrar o ponto ideal: manter a conexão aberta tempo suficiente para aproveitar o cache local do navegador e reduzir latência, mas não tanto a ponto de consumir recursos desnecessários do servidor.

2. Otimizando o Apache no Ubuntu

O Apache lida com conexões através de MPMs (Multi-Processing Modules). A configuração varia dependendo se você está usando prefork, worker ou event. Em versões modernas do Ubuntu, o mpm-event é frequentemente o padrão para PHP-FPM devido à sua eficiência em concorrência.

O arquivo de configuração principal geralmente fica em /etc/apache2/mods-enabled/mpm_event.conf (ou similar, dependendo do módulo ativo). No entanto, os parâmetros de timeout e keepalive são definidos no contexto global ou no arquivo de configurações de conexão.

2.1. Ativando e Configurando o Módulo MPM

Verifique qual módulo está ativo:

a2query -m mpm_event

Se estiver usando PHP com Apache, é comum usar o módulo mod_mpm_event. Edite o arquivo de configuração do MPM:

sudo nano /etc/apache2/mods-available/mpm_event.conf

Dentro deste arquivo, ajuste os limites de processos. Embora não sejam timeouts diretos, eles impactam a capacidade de aceitar novas conexões keepalive:

<IfModule mpm_event_module>
    StartServers             2
    MinSpareThreads         25
    MaxSpareThreads         75
    ThreadLimit             64
    ThreadsPerChild         25
    MaxRequestWorkers      150
    MaxConnectionsPerChild   0
</IfModule>

2.2. Configurando Timeouts e Keepalive no Apache

A configuração específica de timeout e keepalive reside no arquivo conf-enabled/timeout.conf ou diretamente no apache2.conf. Vamos editar o arquivo de configurações adicionais:

sudo nano /etc/apache2/conf-available/timeouts.conf

Crie ou edite o conteúdo com as seguintes diretrizes. Estas são configurações equilibradas para uma VPS média:

<IfModule mod_mime.c>
    # Tempo máximo que o servidor aguarda por um bloco de envio
    # Padrão: 300s. Recomendado: 60-120s para evitar bloqueios longos
    Timeout 120

    # Tempo máximo para receber uma requisição HTTP completa do cliente
    # Se um script demorar mais que isso, ele será interrompido
    # Importante: Deve ser maior que o max_execution_time do PHP
    RequestReadTimeout header=40-120,MinRate=500 body=20,Libcurl-timeout=30

    # Habilita conexões persistentes
    KeepAlive On

    # Número máximo de requisições permitidas por conexão keepalive
    # 0 significa ilimitado (não recomendado para segurança e estabilidade)
    KeepAliveTimeout 5

    # Número máximo de conexões keepalive aguardando no buffer do servidor
    # Aumenta a capacidade de lidar com picos súbitos de tráfego
    MaxKeepAliveRequests 100
</IfModule>

Explicação dos parâmetros:

  • Timeout 120: Define o limite global. Para APIs ou uploads grandes, você pode aumentar, mas para sites institucionais, 60-90s é suficiente.
  • KeepAliveTimeout 5: Este é o valor mais crítico. Um valor de 4 a 5 segundos é o padrão ouro. Se seu site carrega muito rápido e os usuários navegam depressa, você pode testar com 2s. Se seus usuários estão em redes móveis lentas (3G/4G), mantenha 5s ou aumente para 10s.
  • MaxKeepAliveRequests 100: Limita o uso de uma única conexão TCP. Isso evita que um único cliente monopolize a thread do servidor indefinidamente.

Após salvar, verifique a sintaxe e reinicie:

sudo apache2ctl configtest
sudo systemctl restart apache2

3. Otimizando o Nginx no Ubuntu

O Nginx é conhecido por sua arquitetura assíncrona e eficiente no manejo de conexões keepalive. A configuração principal fica em /etc/nginx/nginx.conf. Diferente do Apache, que pode precisar de múltiplos arquivos, o Nginx centraliza essas definições.

3.1. Acessando a Configuração Principal

sudo nano /etc/nginx/nginx.conf

Você deve localizar o bloco http. É dentro deste bloco que as diretrizes globais são aplicadas.

3.2. Diretivas de Timeout e Keepalive no Nginx

Adicione ou modifique as seguintes linhas dentro do bloco http { ... }:

http {
    # Habilita conexões persistentes
    keepalive_timeout 65;
    
    # Tamanho máximo do cabeçalho da requisição (em bytes)
    # Ajuste conforme necessário, padrão é 4k/8k
    client_header_buffer_size 1k;
    large_client_header_buffers 4 8k;

    # Tempo limite para leitura do corpo da requisição (upload)
    # Padrão: 60s. Aumente se você aceita uploads de vídeo/fotos grandes
    client_body_timeout 60;

    # Tempo limite para envio de resposta ao cliente
    send_timeout 60;

    # ... outras configurações ...
}

Análise detalhada das diretivas:

  • keepalive_timeout 65: No Nginx, este valor define quanto tempo uma conexão keepalive permanece aberta após o envio da resposta. O padrão é 75 segundos em algumas versões, mas 65s é um valor seguro que evita timeouts de TCP no meio do caminho (NAT firewalls costumam fechar conexões após ~60-120s). Se você estiver atrás de um balanceador de carga ou CDN, ajuste conforme a configuração deles.
  • client_header_buffer_size: Define o buffer para cabeçalhos pequenos. Aumentar isso pode ajudar em requisições com cookies grandes, mas consome mais memória por conexão.
  • client_body_timeout 60: Se um cliente iniciar o envio de um POST (upload) e parar por mais de 60 segundos, o Nginx fecha a conexão. Isso protege contra ataques de lentidão (slowloris) e libera recursos rapidamente.
  • send_timeout 60: Tempo limite para transferência de dados de resposta. Se um usuário pausar o download, o servidor esperará 60 segundos antes de fechar. Para sites estáticos leves, você pode reduzir para 30s.

3.3. Otimização Avançada: Keepalive no Proxy (Backend)

Se você usa Nginx como reverse proxy para uma aplicação Node.js, Python ou PHP-FPM, é vital configurar o keepalive na comunicação entre o Nginx e o backend.

upstream php-fpm {
    server 127.0.0.1:9000;
    # Mantém conexões abertas com o backend para evitar overhead de conexão constante
    keepalive 32; 
}

server {
    location ~ \.php$ {
        proxy_pass http://php-fpm;
        
        # Passa os headers corretos para manter a conexão
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        
        # Timeout da comunicação com o backend
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }
}

A diretiva keepalive 32 no bloco upstream define quantas conexões inativas com o backend serão mantidas em cache. Isso evita que o Nginx abra e feche conexões TCP para cada requisição PHP, melhorando drasticamente a latência.

4. Ajustes no Sistema Operacional (Ubuntu)

Configurações de aplicação só funcionam bem se o kernel do Linux estiver preparado para lidar com muitas conexões simultâneas. Em VPSs com pouca memória RAM, os limites padrão podem ser baixos.

4.1. Ajustando o Limite de Arquivos e Sockets

Verifique o limite atual de arquivos abertos:

ulimit -n

Se for inferior a 65535, edite o arquivo /etc/security/limits.conf:

sudo nano /etc/security/limits.conf

Adicione as seguintes linhas para garantir que os serviços possam abrir muitas conexões:

* soft nofile 65535
* hard nofile 65535
www-data soft nofile 65535
www-data hard nofile 65535

4.2. Otimização do TCP Stack (sysctl)

Edite o arquivo de configurações do kernel:

sudo nano /etc/sysctl.conf

Adicione ou verifique estas linhas para otimizar o gerenciamento de memória e sockets TCP:

# Aumenta o tamanho máximo da fila de conexões pendentes
net.core.somaxconn = 4096

# Habilita reuso rápido de sockets em estado TIME_WAIT
net.ipv4.tcp_tw_reuse = 1

# Reduz o tempo que uma conexão fica em estado TIME_WAIT
# Padrão é 60s, reduzir para 30s libera memória mais rápido
net.ipv4.tcp_fin_timeout = 30

# Aumenta o espaço de buffer TCP
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216

Para aplicar as mudanças imediatamente sem reiniciar:

sudo sysctl -p

5. Validação e Monitoramento Pós-Configuração

Após aplicar todas as alterações, é essencial validar se o servidor está respondendo conforme esperado.

5.1. Teste de Sintaxe

Sempre teste a configuração antes de reiniciar:

# Para Apache
sudo apache2ctl configtest

# Para Nginx
sudo nginx -t

Se o retorno for successful, reinicie os serviços:

sudo systemctl restart apache2
# ou
sudo systemctl restart nginx

5.2. Monitoramento de Conexões

Use ferramentas de linha de comando para visualizar o impacto. Para ver quantas conexões estão no estado ESTABLISHED (ativas) e TIME_WAIT:

sudo ss -s

O comando ss (socket statistics) é mais rápido e informativo que o antigo netstat. Observe a linha "TCP: eth0" no final. Se você vir um número excessivo de conexões em TIME_WAIT, considere reduzir o tcp_fin_timeout no sysctl ou ajustar o keepalive timeout para um valor menor.

Além disso, monitore o uso de memória RAM e CPU. Um erro comum é definir timeouts altos demais, fazendo com que o servidor retenha milhares de conexões ociosas, consumindo memória RAM desnecessária. Use htop ou top para verificar se o consumo de memória subiu desproporcionalmente após a mudança.

6. Boas Práticas e Considerações Finais

A otimização de timeouts não é um "tamanho único". O valor ideal depende do seu perfil de tráfego:

  • Sites Institucionais/Blogs: Tráfego baixo, usuários navegam lentamente. Keepalive timeout alto (10-30s) ajuda a carregar múltiplos recursos estáticos rapidamente.
  • APIs e Aplicativos Móveis: Muitas requisições pequenas e rápidas. Keepalive é essencial, mas o timeout pode ser menor (5-10s), pois as conexões são estabelecidas frequentemente por bibliotecas HTTP modernas que já otimizam o pooling.
  • E-commerce em Promoções: Priorize a liberação rápida de recursos. Mantenha timeouts moderados e foque em aumentar os limites de processos (MaxRequestWorkers ou worker_processes) para lidar com a concorrência.

Lembre-se também que, se você utiliza uma CDN (como Cloudflare ou AWS CloudFront), as configurações de timeout do seu servidor de origem devem ser compatíveis com a CDN. Se a CDN mantém a conexão keepalive aberta por 300 segundos e seu servidor fecha em 5 segundos, a conexão será fechada prematuramente durante o intervalo entre requisições da CDN para o backend, anulando os benefícios.

Ajustar timeouts e keepalive é um exercício de equilíbrio. Comece com os valores recomendados neste guia, monitore o desempenho por alguns dias e ajuste finamente conforme a resposta real dos seus usuários. A estabilidade do servidor depende tanto de saber quando fechar uma conexão quanto de saber quando mantê-la viva.

Compartilhar: Link copiado!
Esse tutorial foi útil?

Comentários (0)

Seja o primeiro a comentar.

Deixe seu comentário

Seu comentário será analisado antes de ser publicado.

0/2000