Proxy inverso Nginx che causa il timeout del gateway 504


127

Sto usando Nginx come proxy inverso che accetta le richieste, quindi esegue un proxy_pass per ottenere l'applicazione Web effettiva dal server upstream in esecuzione sulla porta 8001.

Se vado su mywebsite.com o faccio una scommessa, ottengo un timeout del gateway 504 dopo 60 secondi ... Tuttavia, se carico mywebsite.com:8001, l'applicazione si carica come previsto!

Quindi qualcosa impedisce a Nginx di comunicare con il server upstream.

Tutto questo è iniziato dopo che la mia società di hosting ha ripristinato la macchina su cui era in esecuzione la mia roba, prima di allora nessun problema.

Ecco il mio blocco server vhosts:

server {
    listen   80;
    server_name mywebsite.com;

    root /home/user/public_html/mywebsite.com/public;

    access_log /home/user/public_html/mywebsite.com/log/access.log upstreamlog;
    error_log /home/user/public_html/mywebsite.com/log/error.log;

    location / {
        proxy_pass http://xxx.xxx.xxx.xxx:8001;
        proxy_redirect off;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
} 

E l'output dal mio registro errori Nginx:

2014/06/27 13:10:58 [error] 31406#0: *1 upstream timed out (110: Connection timed out) while connecting to upstream, client: xxx.xx.xxx.xxx, server: mywebsite.com, request: "GET / HTTP/1.1", upstream: "http://xxx.xxx.xxx.xxx:8001/", host: "mywebsite.com"

Il server esegue SELinux?
CrackerJack9,

Nel mio caso, il problema era rappresentato dal gateway NAT, non dall'API NGINX o back-end. stackoverflow.com/a/62351959/9956279
Sushilinux

Risposte:


152

Probabilmente è possibile aggiungere qualche riga in più per aumentare il periodo di timeout a monte. Gli esempi seguenti impostano il timeout su 300 secondi:

proxy_connect_timeout       300;
proxy_send_timeout          300;
proxy_read_timeout          300;
send_timeout                300;

5
Penso che aumentare raramente il timeout sia raramente la risposta a meno che tu non sappia che la tua rete / servizio risponderà sempre o in alcuni casi molto lentamente. Poche richieste web al giorno d'oggi dovrebbero richiedere più di qualche secondo a meno che non si stia scaricando contenuto (file / immagini)
Almund

@Almund ho pensato la stessa cosa (quasi non si è preso la briga di provare questo), ma per qualsiasi motivo questo ha funzionato per me. (In precedenza scaduto dopo 60 secondi, ora ricevi immediatamente la risposta).
Dax Fohl,

@Dax Fohl: È curioso. Ho tirato giù la fonte e ho dato una rapida occhiata e da quello che posso vedere, l'impostazione di qualsiasi impostazione proxy_ oltre a proxy_pass inizializzerà un gruppo di impostazioni che presumo faranno funzionare il proxy in un modo diverso, quindi forse l'impostazione di qualcosa darà lo stesso comportamento.
Mandorla

Non ho risolto il problema per me usandolo con un server
nodejs

3
Trovo che ho solo bisogno del proxy_read_timeoutdebug sul backend. Grazie!
Jeff Puckett,

79

L'aumento del timeout probabilmente non risolverà il problema poiché, come dici tu, l'effettivo web server di destinazione sta rispondendo bene.

Ho avuto lo stesso problema e ho scoperto che aveva a che fare con il non usare un keep-alive sulla connessione. In realtà non posso rispondere perché questo è, ma, cancellando l'intestazione della connessione, ho risolto questo problema e la richiesta è stata inviata correttamente:

server {
    location / {
        proxy_set_header   X-Real-IP $remote_addr;
        proxy_set_header   Host      $http_host;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
        proxy_pass http://localhost:5000;
    }
}

Dai un'occhiata a questo post che lo spiega in modo più dettagliato: nginx chiude la connessione a monte dopo la richiesta Chiarimento dell'intestazione keep-alive http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive


7
MESI di problemi risolti da una sola riga proxy_set_header Connection "";lol, non usare runcloud
annuisce il

21

user2540984 , così come molti altri hanno sottolineato che puoi provare ad aumentare le impostazioni di timeout. Io stesso ho affrontato un problema simile a questo e ho provato a cambiare le mie impostazioni di timeout nel file /etc/nginx/nginx.conf , come quasi tutti in questi thread suggeriscono. Questo, tuttavia, non mi ha aiutato un po '; non vi è stato alcun cambiamento evidente nelle impostazioni di timeout di NGINX. Dopo molte ore di ricerche, sono finalmente riuscito a risolvere il mio problema.

La soluzione sta in questo thread del forum e ciò che dice è che dovresti mettere le tue impostazioni di timeout in /etc/nginx/conf.d/timeout.conf (e se questo file non esiste, dovresti crearlo). Ho usato le stesse impostazioni suggerite nel thread:

proxy_connect_timeout 600;
proxy_send_timeout 600;
proxy_read_timeout 600;
send_timeout 600;

Questa potrebbe non essere la soluzione al tuo problema particolare, ma se qualcun altro nota che il timeout cambia in /etc/nginx/nginx.conf non fa nulla, spero che questa risposta ti aiuti!


ciao non c'è timeout.conf nella mia directory config.d. Hai detto di crearlo e voglio confermare basta aggiungere l'impostazione sopra in timeout.conf?
tktktk0711,

Sì, basta aggiungerli. Puoi modificarli per le tue esigenze, ma questi hanno funzionato per me!
Andreas Forslöw,

Sfortunatamente, nella fattoria di Laravel con Ubuntu e Nginx, questo non funziona. :( Intendi semplicemente aggiungere quelle righe? Senza server{}o qualcos'altro? Questo errore viene visualizzato subito dopo 5 minuti. Ricaricare, riavviare e non riesco mai a superare quei 5 minuti o 300 secondi. Ci sono altre idee da risolvere vero?
Pathros,

15

Se si desidera aumentare o aggiungere un limite di tempo a tutti i siti, è possibile aggiungere le righe seguenti al nginx.conffile.

Aggiungi le righe sottostanti alla httpsezione /usr/local/etc/nginx/nginx.confo al /etc/nginx/nginx.conffile.

fastcgi_read_timeout 600;
proxy_read_timeout 600;

Se le righe sopra non esistono nel conffile, aggiungile, altrimenti aumenta fastcgi_read_timeoute proxy_read_timeoutassicurati che nginx e php-fpm non siano scaduti.

Per aumentare il limite di tempo per un solo sito, puoi modificare in vim /etc/nginx/sites-available/example.com

location ~ \.php$ {
    include /etc/nginx/fastcgi_params;
        fastcgi_pass  unix:/var/run/php5-fpm.sock;
    fastcgi_read_timeout 300; 
}

e dopo aver aggiunto queste righe nginx.conf, non dimenticare di riavviare nginx.

service php7-fpm reload 
service nginx reload

oppure, se stai usando il parcheggiatore, digita semplicemente valet restart.


1
Grazie funziona per me:fastcgi_read_timeout 600; proxy_read_timeout 600;
Alejandro

13

Puoi anche affrontare questa situazione se il tuo server upstream utilizza un nome di dominio e il suo indirizzo IP cambia (ad es. I tuoi punti upstream verso un AWS Elastic Load Balancer)

Il problema è che nginx risolverà l'indirizzo IP una volta e lo manterrà nella cache per le richieste successive fino al ricaricamento della configurazione.

Puoi dire a nginx di utilizzare un server dei nomi per risolvere nuovamente il dominio una volta scaduta la voce memorizzata nella cache:

location /mylocation {
    # use google dns to resolve host after IP cached expires
    resolver 8.8.8.8;
    set $upstream_endpoint http://your.backend.server/;
    proxy_pass $upstream_endpoint;
}

I documenti su proxy_pass spiegano perché questo trucco funziona:

Il valore del parametro può contenere variabili. In questo caso, se un indirizzo viene specificato come nome di dominio, il nome viene cercato tra i gruppi di server descritti e, se non trovato, viene determinato utilizzando un resolver.

Complimenti a "Nginx con upstream dinamici" (tenzer.dk) per la spiegazione dettagliata, che contiene anche alcune informazioni rilevanti su un avvertimento di questo approccio per quanto riguarda gli URI trasmessi.


1
questa risposta è oro, esattamente quello che mi è successo. i punti a monte indicano aws elb e l'improvviso timeout del gateway.
Nathan Do il

2

Ho avuto lo stesso problema. Si è scoperto che era causato dal tracciamento della connessione iptables sul server upstream. Dopo aver rimosso --state NEW,ESTABLISHED,RELATEDdallo script del firewall e cancellato conntrack -Fil problema era sparito.


0

NGINX stesso potrebbe non essere la causa principale.

Se le "porte minime per istanza VM" impostate sul gateway NAT - che si trovano tra l'istanza NGINX e la proxy_passdestinazione - sono troppo piccole per il numero di richieste simultanee, è necessario aumentarle.

Soluzione: aumentare il numero disponibile di porte per VM su NAT Gateway.

Contesto Nel mio caso, su Google Cloud, un proxy inverso NGINX è stato inserito in una sottorete, con un gateway NAT. L'istanza NGINX stava reindirizzando le richieste a un dominio associato alla nostra API back-end (upstream) tramite il gateway NAT.

Questa documentazione di GCP ti aiuterà a capire come NAT è rilevante per il timeout di NGINX 504.


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.