Ajuste de Buffer do Nginx: Otimizando `client_body_buffer_size` e `proxy_buffer_size`

Otimize o desempenho do Nginx dominando o ajuste de buffer. Este guia detalha como configurar `client_body_buffer_size`, `proxy_buffer_size` e `proxy_buffers` para minimizar a lenta E/S de disco durante uploads e tratamento de respostas. Aprenda exemplos práticos para garantir que seus dados permaneçam em buffers de memória rápida, melhorando a latência para aplicações de alto desempenho.

53 visualizações

Ajuste de Buffer do Nginx: Otimizando client_body_buffer_size e proxy_buffer_size

O Nginx é renomado por seu alto desempenho, eficiência e escalabilidade, frequentemente servindo como um robusto proxy reverso, balanceador de carga ou servidor web. Um aspecto crítico para alcançar o desempenho máximo reside na configuração correta de seus mecanismos internos de buffer. Os buffers ditam como o Nginx lida com os corpos de requisição de entrada (para uploads ou dados POST) e respostas do upstream de saída. A configuração incorreta pode levar a um consumo excessivo de memória ou, inversamente, a lentas operações de I/O em disco, anulando as vantagens de velocidade do Nginx.

Este guia mergulha profundamente nas diretivas de buffer principais — client_body_buffer_size, proxy_buffer_size, e configurações relacionadas — explicando sua função, impacto e fornecendo passos acionáveis para ajustá-las de acordo com sua carga de trabalho específica. O ajuste eficaz do buffer previne a troca desnecessária de dados para o disco, melhorando diretamente a latência de resposta e o throughput geral.

Entendendo os Fundamentos do Buffer do Nginx

O Nginx usa buffers para armazenar temporariamente dados que fluem através de seus processos, seja dados de um cliente para o servidor, ou do servidor para uma aplicação backend upstream.

Quando um buffer é preenchido, o Nginx deve decidir se continua o buffer na memória ou se despeja o excesso de dados em um arquivo temporário no disco. O I/O de disco é significativamente mais lento que o acesso à memória, portanto, o objetivo do ajuste é garantir que os tamanhos típicos de requisição/resposta caibam confortavelmente nos buffers de memória.

Visão Geral das Diretivas de Buffer Principais

Várias diretivas controlam o buffering, muitas vezes dependendo do contexto (comunicação com cliente, proxying ou FastCGI):

  • client_body_buffer_size: Controla o tamanho do buffer usado para ler o corpo da requisição do cliente (usado em requisições POST, uploads de arquivos, etc.).
  • proxy_buffer_size: Controla o tamanho do buffer usado para ler respostas de um servidor upstream ao atuar como proxy reverso.
  • proxy_buffers: Define o número e o tamanho dos buffers usados para ler respostas do servidor upstream quando os dados excedem proxy_buffer_size.
  • fastcgi_buffer_size e fastcgi_buffers: Diretivas semelhantes específicas para comunicação FastCGI (ex: PHP-FPM).

Ajustando client_body_buffer_size

Esta diretiva é crucial quando o Nginx lida diretamente com grandes uploads ou submissões de formulário extensas.

Comportamento Padrão e Impacto

Por padrão, o Nginx geralmente define client_body_buffer_size para um valor relativamente pequeno (frequentemente 8k ou 16k, dependendo da versão). Se o corpo da requisição do cliente exceder este tamanho, o Nginx começa a escrever os dados excedentes em um arquivo temporário no disco (client_body_temp_path).

Impacto: Se você antecipa lidar com requisições maiores que o tamanho de buffer padrão, mas menores que a sua RAM disponível permite, aumentar este valor pode prevenir escritas lentas no disco.

Exemplo de Configuração

A diretiva é definida nos contextos http, server ou location:

http {
    # Define o tamanho do buffer para corpos de requisição do cliente para 128KB
    client_body_buffer_size 128k;
    ...
}

Melhor Prática: Defina este valor com base no tamanho típico máximo dos dados POST que você espera, e não no tamanho máximo absoluto de upload permitido. Se você o definir muito alto globalmente, e muitos clientes enviarem requisições moderadamente grandes simultaneamente, você corre o risco de consumir memória excessiva em todos os processos de worker.

Otimizando Buffers de Proxy Reverso: proxy_buffer_size e proxy_buffers

Quando o Nginx atua como um proxy reverso, a principal preocupação muda para o buffer da resposta que retorna do servidor upstream (ex: Apache, Tomcat ou uma aplicação Node.js).

proxy_buffer_size

Define o tamanho do buffer inicial usado para ler o cabeçalho da resposta e o primeiro bloco do corpo da resposta do servidor upstream.

proxy_buffers (Número e Tamanho)

Se o corpo da resposta do upstream for grande, o Nginx usa um conjunto de buffers definidos por proxy_buffers. Esta diretiva aceita dois argumentos:

  1. O número de buffers.
  2. O tamanho de cada buffer.

Se os dados da resposta excederem o espaço total de buffer alocado (Número * Tamanho), o Nginx começará a escrever os dados restantes no disco no diretório proxy_temp_path.

Exemplo de Configuração (Contexto Proxy)

Para garantir que grandes respostas de um servidor upstream permaneçam na memória, você pode configurar os buffers do proxy da seguinte forma:

location /api/ {
    proxy_pass http://backend_servers;

    # Define o tamanho inicial do buffer para 64k
    proxy_buffer_size 64k;

    # Usa 8 buffers, cada um com 128k de tamanho, para o restante da resposta.
    # Capacidade total do buffer: 8 * 128k = 1MB
    proxy_buffers 8 128k;

    # Define o tamanho máximo que pode ser escrito temporariamente no disco antes que o Nginx comece a enviar dados para o cliente
    proxy_max_temp_file_size 10m;
}

Dica: Se o seu backend tipicamente retorna grandes payloads JSON ou arquivos estáticos grandes, investigue o tamanho típico da resposta e defina proxy_buffers grande o suficiente para cobrir 95% dessas respostas. Você pode precisar aumentar proxy_buffer_size se o servidor upstream enviar cabeçalhos de resposta grandes.

Gerenciando o Despejo para Disco (proxy_max_temp_file_size)

Se o Nginx ficar sem espaço de buffer de memória (conforme definido por proxy_buffers ou client_body_buffer_size), ele despeja o excesso para o disco. A diretiva que controla quando isso acontece é *_temp_file_size.

Por padrão, o Nginx permite que arquivos temporários cresçam indefinidamente, o que pode consumir espaço em disco rapidamente sob alta carga.

proxy_max_temp_file_size

Isto limita o tamanho do arquivo temporário que o Nginx pode criar ao armazenar em buffer respostas upstream. Definir isso como 0 desabilita totalmente o uso de arquivos temporários, forçando o Nginx a armazenar em buffer na memória ou retornar um erro (ou fechar a conexão, dependendo do contexto) se o buffer for excedido.

# Exemplo: Se o buffer exceder a memória, pare de escrever no disco após 20MB
proxy_max_temp_file_size 20m;

# Exemplo: Desabilita completamente o despejo para disco (use com cautela e RAM suficiente)
proxy_max_temp_file_size 0;

Aviso sobre proxy_max_temp_file_size 0: Embora elimine o I/O de disco, se seus processos de worker lidarem com inúmeras requisições concorrentes que excedam o espaço total de buffer alocado, você pode enfrentar erros de esgotamento de memória ou fechamentos de conexão inesperados se o Nginx não conseguir processar o fluxo de dados.

Ajustando Buffers FastCGI (fastcgi_buffer_size)

Para aplicações que se comunicam via FastCGI (como PHP), a lógica de buffer é semelhante, mas usa diretivas dedicadas.

fastcgi_buffer_size define o tamanho do buffer para ler o cabeçalho e a parte inicial da resposta FastCGI. fastcgi_buffers define o array de buffers usados para ler os dados do corpo subsequentes.

location ~ \.php$ {
    include fastcgi_params;
    fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;

    # Define os buffers FastCGI para 16 buffers de 16k cada
    fastcgi_buffers 16 16k;

    # Se a resposta for muito grande, ajuste o tamanho
    fastcgi_buffer_size 128k;
}

Resumo e Estratégia de Ajuste

O ajuste eficaz do buffer é um ato de equilíbrio entre a disponibilidade de memória do sistema e as características da carga de trabalho.

  1. Analise a Carga de Trabalho: Determine o tamanho típico dos corpos de requisição do cliente e das respostas upstream.
  2. Corpo do Cliente: Defina client_body_buffer_size para cobrir o tamanho típico maior de dados POST/upload.
  3. Respostas do Proxy: Defina proxy_buffers (contagem e tamanho) grandes o suficiente para acomodar a maioria das respostas de backend na RAM.
  4. Limite o Despejo: Use proxy_max_temp_file_size para limitar o uso de disco resultante de estouros de buffer, ou defina-o como 0 somente se você tiver certeza de que sua alocação de memória é suficiente.

Lembre-se de testar o desempenho minuciosamente após as alterações de configuração e monitorar a utilização da memória do sistema.

# Após alterar o nginx.conf, sempre teste a sintaxe antes de recarregar
nginx -t

# Em seguida, recarregue o Nginx para aplicar as alterações sem derrubar as conexões
systemctl reload nginx