Resolvendo Problemas de Timeout de Gateway 504 e Timeout do Cliente no Nginx

Domine os timeouts do Nginx, incluindo o temido Timeout de Gateway 504, aprendendo a ajustar diretivas críticas de proxy. Este guia detalha como aumentar `proxy_read_timeout`, otimizar o buffering e usar logs de erro para diagnosticar falhas de comunicação entre o Nginx e servidores upstream para um robusto gerenciamento de conexões.

63 visualizações

Resolução de Problemas de Nginx 504 Gateway Timeout e Timeout do Cliente

Nginx, embora conhecido por seu alto desempenho e estabilidade, pode, às vezes, apresentar erros frustrantes, mais notavelmente códigos de status HTTP indicando uma falha na comunicação. Entre os mais comuns estão o 504 Gateway Timeout e vários timeouts do lado do cliente. Esses problemas quase sempre resultam de uma incompatibilidade entre o tempo que o Nginx espera por uma resposta de um serviço de backend (como um servidor de aplicação ou outro proxy) e o tempo que o cliente (navegador ou serviço upstream) está disposto a esperar pelo próprio Nginx.

Este guia abrangente o guiará pelo diagnóstico da causa raiz desses timeouts e fornecerá ajustes de configuração concretos para resolver erros 504 e melhorar a estabilidade geral da conexão. Compreender esses mecanismos é crucial para manter a alta disponibilidade, especialmente em arquiteturas de microsserviços ou ao lidar com aplicações upstream de resposta lenta.


Compreendendo o Erro 504 Gateway Timeout

Um erro 504 Gateway Timeout ocorre quando o Nginx, atuando como um proxy reverso ou gateway, não recebe uma resposta oportuna do servidor upstream para o qual está encaminhando as requisições. Em termos simples: o Nginx pediu uma resposta ao backend, esperou pelo tempo configurado e desistiu porque nenhuma resposta chegou.

Isso é distinto de um 502 Bad Gateway (que implica uma resposta inválida do upstream) ou um 503 Service Unavailable (que implica que o upstream está atualmente sobrecarregado ou indisponível).

Diretivas Chave para Controlar Upstream Timeouts

Ao realizar o proxy de requisições, o Nginx usa várias diretivas críticas, localizadas principalmente dentro dos blocos http, server ou location, ou especificamente dentro de um bloco upstream. Ajustar esses valores é o método principal para resolver erros 504.

1. proxy_connect_timeout

Isso define o timeout para estabelecer uma conexão com o servidor upstream. Se o Nginx não conseguir conectar-se dentro desse período, ele retorna um erro de timeout.

Padrão: 60 segundos

proxy_connect_timeout 60s;

2. proxy_send_timeout

Isso define o timeout para o tempo entre duas operações de escrita sucessivas para o servidor upstream. Isso é relevante ao enviar um corpo de requisição grande.

Padrão: 60 segundos

proxy_send_timeout 60s;

3. proxy_read_timeout (A Correção Mais Comum para 504s)

Isso define o timeout para aguardar uma resposta do servidor upstream depois que os cabeçalhos da requisição foram enviados. Se a aplicação de backend demorar muito para processar a requisição e gerar um corpo de resposta, esta é a diretiva que precisa ser aumentada.

Padrão: 60 segundos

# Exemplo: Aumentando o timeout de leitura para 120 segundos para uma API lenta
proxy_read_timeout 120s;

Boa Prática: Se sua aplicação frequentemente excede o padrão de 60 segundos, aumente este valor com cautela. Um valor muito alto pode mascarar problemas fundamentais de desempenho do backend.


Lidando com Timeouts do Lado do Cliente

Enquanto o 504 se relaciona com a comunicação Nginx-para-Backend, os timeouts do lado do cliente ocorrem quando o cliente (por exemplo, um navegador, aplicativo móvel ou outro serviço fazendo uma requisição para o Nginx) desiste de esperar antes mesmo que o Nginx tenha terminado de se comunicar com o backend.

Se você está experimentando timeouts do cliente antes que o Nginx registre um 504, você precisa analisar a conexão entre o cliente e o Nginx.

1. Keepalive do Lado do Cliente

Se o cliente fechar a conexão prematuramente, o Nginx pode receber um erro ou o cliente pode simplesmente atingir o timeout esperando por dados.

Certifique-se de que as configurações de conexão do lado do cliente (se configuráveis) não sejam muito agressivas. Se o cliente for outro proxy ou balanceador de carga, verifique suas configurações de timeout em relação ao send_timeout do Nginx.

2. send_timeout do Nginx

Esta diretiva controla por quanto tempo o Nginx esperará que o cliente confirme ou receba dados (o tempo entre duas operações de escrita sucessivas para o cliente).

Padrão: 60 segundos

# Defina isso se os clientes estiverem atingindo o timeout enquanto o Nginx está enviando a resposta
send_timeout 120s;

Otimizando o Buffering para Respostas Grandes

Às vezes, os timeouts ocorrem não porque o processamento demorou muito, mas porque o Nginx começou a armazenar a resposta do upstream em buffer e falhou em completar a escrita do buffer antes que a conexão atingisse o timeout. Isso é particularmente relevante ao lidar com respostas muito grandes.

O Nginx usa buffers para armazenar temporariamente dados recebidos do upstream antes de enviá-los ao cliente. Se a resposta for muito grande, esses buffers podem ser excedidos, levando a um tratamento complexo ou latência percebida.

Diretivas Chave de Buffering

Estas são geralmente definidas dentro do bloco location ou server:

Diretiva Propósito
proxy_buffers Define o número e o tamanho dos buffers usados para ler o cabeçalho da resposta do upstream. Formato: número tamanho;
proxy_buffer_size Define o tamanho do primeiro buffer, que é usado para ler o cabeçalho da resposta.
proxy_max_temp_file_size Se a resposta exceder os buffers disponíveis, o Nginx escreve em arquivos temporários. Isso define o tamanho máximo para esses arquivos temporários.

Exemplo de Configuração para Grandes Volumes/Respostas Grandes:

location /api/heavy_report {
    proxy_pass http://backend_app;

    # Aumentar o timeout de leitura
    proxy_read_timeout 180s;

    # Ajustar o buffering para corpos de resposta potencialmente grandes
    # Usar 8 buffers, cada um de até 1MB (1024k)
    proxy_buffers 8 1024k;
    proxy_buffer_size 256k;

    # Permitir arquivos temporários de até 500MB se os buffers estourarem
    proxy_max_temp_file_size 500m;
}

Dica sobre Buffering: Se sua resposta de backend for realmente enorme (por exemplo, vários GBs), considere servir conteúdo estático ou implementar streaming diretamente, pois o buffering de respostas extremamente grandes pode consumir uma memória significativa no servidor Nginx.


Etapas de Resolução de Problemas e Análise de Logs

Resolver timeouts requer identificar onde o atraso ocorreu: Cliente -> Nginx, ou Nginx -> Backend.

Passo 1: Verificar os Logs de Erro do Nginx

O log de erro do Nginx é sua fonte definitiva para determinar se o Nginx atingiu o timeout esperando pelo backend.

Procure por entradas contendo frases como:

  • upstream timed out (110: Connection timed out)
  • upstream prematurely closed connection while reading response header from upstream

Se você vir essas, o problema reside no proxy_read_timeout ou no tempo de processamento do backend.

Passo 2: Verificar os Logs da Aplicação Backend

Se o Nginx atingir o timeout (os logs indicam 504), verifique imediatamente os logs do serviço upstream (por exemplo, logs do PHP-FPM, logs do Gunicorn, logs do servidor de aplicação Java). Você precisa confirmar se a requisição sequer chegou ao backend e quanto tempo levou para ser concluída.

  • Se os logs do backend mostrarem que a requisição levou mais tempo do que o seu proxy_read_timeout configurado, aumente o timeout do Nginx.
  • Se os logs do backend mostrarem que a requisição foi concluída rapidamente, o problema pode ser latência de rede entre o Nginx e o backend, ou um timeout de cliente mal configurado voltado para o Nginx.

Passo 3: Usar o Cabeçalho X-Upstream-Response-Time (Opcional)

Para diagnósticos detalhados, você pode registrar o tempo exato que o upstream levou para responder usando a variável $upstream_response_time no formato do seu log de acesso. Isso ajuda a confirmar o desempenho real do backend.

No seu nginx.conf:

log_format proxy_detailed '$remote_addr - $remote_user [$time_local] "$request" '
                        '$status $body_bytes_sent "$http_referer" '
                        '"$http_user_agent" $request_time $upstream_response_time';

access_log /var/log/nginx/access.log proxy_detailed;

Ao analisar $upstream_response_time, você pode ver a duração precisa que o Nginx esperou, independentemente das configurações de timeout do próprio Nginx.


Resumo e Aplicação de Mudanças

Resolver problemas de timeout do Nginx geralmente envolve um ato de equilíbrio entre as expectativas do cliente e as capacidades de processamento do backend. Lembre-se da relação:

  • 504 Timeout: O backend está muito lento ou o link de rede falhou enquanto o Nginx esperava (proxy_read_timeout).
  • Timeout do Cliente: O cliente desistiu de esperar pelo Nginx (send_timeout ou configuração do cliente).

Após fazer quaisquer alterações de configuração (por exemplo, aumentar timeouts ou ajustar tamanhos de buffer), sempre teste a sintaxe da configuração e recarregue o Nginx:

sudo nginx -t
sudo systemctl reload nginx

Monitore cuidadosamente seus logs após aplicar as correções, pois aumentar cegamente os timeouts pode mascarar gargalos de desempenho subjacentes do sistema que exigem otimização em vez de soluções alternativas de configuração.