Risoluzione dei problemi di Nginx 504 Gateway Timeout e di Timeout del Client

Padroneggia i timeout di Nginx, inclusi i temuti 504 Gateway Timeout, imparando a regolare le direttive proxy critiche. Questa guida spiega in dettaglio come aumentare `proxy_read_timeout`, ottimizzare il buffering e usare i log degli errori per diagnosticare i fallimenti di comunicazione tra Nginx e i server upstream, garantendo una gestione robusta delle connessioni.

56 visualizzazioni

Risoluzione degli errori Nginx 504 Gateway Timeout e Client Timeout

Nginx, sebbene noto per le sue alte prestazioni e stabilità, può talvolta presentare errori frustranti, in particolare codici di stato HTTP che indicano un'interruzione nella comunicazione. Tra i più comuni vi sono il 504 Gateway Timeout e vari timeout lato client. Questi problemi derivano quasi sempre da una discrepanza tra il tempo che Nginx attende una risposta da un servizio backend (come un server applicativo o un altro proxy) e il tempo che il client (browser o servizio upstream) è disposto ad attendere Nginx stesso.

Questa guida completa ti accompagnerà nella diagnosi della causa principale di questi timeout e fornirà aggiustamenti concreti di configurazione per risolvere gli errori 504 e migliorare la stabilità generale della connessione. Comprendere questi meccanismi è cruciale per mantenere un'elevata disponibilità, specialmente nelle architetture a microservizi o quando si ha a che fare con applicazioni upstream a lenta risposta.


Comprensione dell'errore 504 Gateway Timeout

Un errore 504 Gateway Timeout si verifica quando Nginx, agendo come reverse proxy o gateway, non riceve una risposta tempestiva dal server upstream a cui sta inoltrando le richieste. In parole semplici: Nginx ha chiesto una risposta al backend, ha atteso per il tempo configurato e ha rinunciato perché non è arrivata alcuna risposta.

Ciò è distinto da un 502 Bad Gateway (che implica una risposta non valida dall'upstream) o da un 503 Service Unavailable (che implica che l'upstream è attualmente sovraccarico o non disponibile).

Direttive chiave che controllano i timeout upstream

Quando inoltra le richieste, Nginx utilizza diverse direttive critiche, principalmente situate all'interno dei blocchi http, server o location, o specificamente all'interno di un blocco upstream. La modifica di questi valori è il metodo principale per risolvere gli errori 504.

1. proxy_connect_timeout

Questo imposta il timeout per la creazione di una connessione con il server upstream. Se Nginx non riesce a connettersi entro questo periodo, restituisce un errore di timeout.

Predefinito: 60 secondi

proxy_connect_timeout 60s;

2. proxy_send_timeout

Questo imposta il timeout per il tempo tra due operazioni di scrittura successive al server upstream. Ciò è rilevante quando si invia un corpo di richiesta di grandi dimensioni.

Predefinito: 60 secondi

proxy_send_timeout 60s;

3. proxy_read_timeout (La soluzione più comune per i 504)

Questo imposta il timeout per l'attesa di una risposta dal server upstream dopo che le intestazioni della richiesta sono state inviate. Se l'applicazione backend impiega troppo tempo per elaborare la richiesta e generare un corpo di risposta, questa è la direttiva che deve essere aumentata.

Predefinito: 60 secondi

# Esempio: Aumento del timeout di lettura a 120 secondi per un'API lenta
proxy_read_timeout 120s;

Best Practice: Se la tua applicazione supera frequentemente i 60 secondi predefiniti, aumenta questo valore con cautela. Un valore molto alto potrebbe mascherare problemi fondamentali di prestazioni del backend.


Affrontare i timeout lato client

Mentre il 504 riguarda la comunicazione Nginx-Backend, i timeout lato client si verificano quando il client (ad es. un browser, un'app mobile o un altro servizio che effettua una richiesta a Nginx) rinuncia all'attesa prima ancora che Nginx abbia finito di comunicare con il backend.

Se stai riscontrando timeout lato client prima che Nginx registri un 504, devi esaminare la connessione tra il client e Nginx.

1. Keepalive lato client

Se il client chiude la connessione prematuramente, Nginx potrebbe ricevere un errore o il client potrebbe semplicemente andare in timeout in attesa di dati.

Assicurati che le impostazioni di connessione lato client (se configurabili) non siano troppo aggressive. Se il client è un altro proxy o load balancer, controlla le sue impostazioni di timeout rispetto a send_timeout di Nginx.

2. send_timeout di Nginx

Questa direttiva controlla quanto tempo Nginx attenderà che il client riconosca o riceva dati (il tempo tra due operazioni di scrittura successive al client).

Predefinito: 60 secondi

# Imposta questo se i client vanno in timeout mentre Nginx sta inviando la risposta
send_timeout 120s;

Ottimizzazione del buffering per risposte di grandi dimensioni

A volte, i timeout si verificano non perché l'elaborazione ha richiesto troppo tempo, ma perché Nginx ha iniziato a memorizzare nella cache la risposta upstream e poi non è riuscito a completare la scrittura nel buffer prima che la connessione andasse in timeout. Ciò è particolarmente rilevante quando si ha a che fare con risposte molto grandi.

Nginx utilizza buffer per contenere temporaneamente i dati ricevuti dall'upstream prima di inviarli al client. Se la risposta è molto grande, questi buffer possono essere superati, portando a una gestione complessa o a una latenza percepita.

Direttive chiave di buffering

Queste sono solitamente impostate all'interno del blocco location o del blocco server:

Direttiva Scopo
proxy_buffers Imposta il numero e la dimensione dei buffer utilizzati per la lettura dell'intestazione della risposta dall'upstream. Formato: numero dimensione;
proxy_buffer_size Imposta la dimensione del primo buffer, che viene utilizzato per leggere l'intestazione della risposta.
proxy_max_temp_file_size Se la risposta supera i buffer disponibili, Nginx scrive su file temporanei. Questo imposta la dimensione massima per questi file temporanei.

Esempio di configurazione per alto volume/grandi risposte:

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

    # Aumenta il timeout di lettura
    proxy_read_timeout 180s;

    # Ottimizza il buffering per corpi di risposta potenzialmente grandi
    # Utilizza 8 buffer, ciascuno fino a 1MB (1024k)
    proxy_buffers 8 1024k;
    proxy_buffer_size 256k;

    # Consenti file temporanei fino a 500MB se i buffer si esauriscono
    proxy_max_temp_file_size 500m;
}

Suggerimento sul buffering: Se la risposta del tuo backend è veramente enorme (ad esempio, diversi GB), considera di servire contenuti statici o di implementare lo streaming direttamente, poiché il buffering di risposte estremamente grandi può consumare una notevole quantità di memoria sul server Nginx.


Passaggi per la risoluzione dei problemi e analisi dei log

La risoluzione dei timeout richiede di individuare dove si è verificato il blocco: Client -> Nginx, o Nginx -> Backend.

Passaggio 1: Controlla i log di errore di Nginx

Il log di errore di Nginx è la tua fonte definitiva per determinare se Nginx è andato in timeout in attesa del backend.

Cerca voci contenenti frasi come:

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

Se vedi queste, il problema risiede in proxy_read_timeout o nel tempo di elaborazione del backend.

Passaggio 2: Controlla i log dell'applicazione backend

Se Nginx va in timeout (i log indicano 504), controlla immediatamente i log del servizio upstream (ad es. log PHP-FPM, log Gunicorn, log del server applicativo Java). Devi confermare se la richiesta ha raggiunto il backend e quanto tempo ha impiegato per essere completata.

  • Se i log del backend mostrano che la richiesta ha impiegato più tempo del proxy_read_timeout configurato, aumenta il timeout di Nginx.
  • Se i log del backend mostrano che la richiesta è stata completata rapidamente, il problema potrebbe essere la latenza di rete tra Nginx e il backend, o un timeout client mal configurato che si affaccia su Nginx.

Passaggio 3: Utilizza l'intestazione X-Upstream-Response-Time (Opzionale)

Per una diagnostica dettagliata, puoi registrare il tempo esatto impiegato dall'upstream per rispondere utilizzando la variabile $upstream_response_time nel formato del tuo log di accesso. Ciò aiuta a confermare le prestazioni effettive del backend.

Nel tuo 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;

Analizzando $upstream_response_time, puoi vedere la durata precisa per cui Nginx ha atteso, indipendentemente dalle impostazioni di timeout di Nginx.


Riepilogo e applicazione delle modifiche

La risoluzione dei problemi di timeout di Nginx comporta generalmente un atto di bilanciamento tra le aspettative del client e le capacità di elaborazione del backend. Ricorda la relazione:

  • 504 Timeout: Il backend è troppo lento o il collegamento di rete è fallito mentre Nginx attendeva (proxy_read_timeout).
  • Client Timeout: Il client ha rinunciato ad attendere Nginx (send_timeout o impostazione client).

Dopo aver apportato qualsiasi modifica alla configurazione (ad es. aumentando i timeout o modificando le dimensioni dei buffer), testa sempre la sintassi della configurazione e ricarica Nginx:

sudo nginx -t
sudo systemctl reload nginx

Monitora attentamente i tuoi log dopo aver applicato le correzioni, poiché l'aumento indiscriminato dei timeout può mascherare colli di bottiglia delle prestazioni del sistema sottostanti che richiedono ottimizzazione piuttosto che soluzioni alternative di configurazione.