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_timeoutconfigurato, 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_timeouto 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.