Nginx Reverse Proxy verursacht 504 Gateway Timeout

127

Ich verwende Nginx als Reverse-Proxy, der Anforderungen entgegennimmt und dann einen Proxy-Pass ausführt, um die eigentliche Webanwendung vom Upstream-Server abzurufen, der auf Port 8001 ausgeführt wird.

Wenn ich zu mywebsite.com gehe oder ein Wget mache, erhalte ich nach 60 Sekunden ein 504 Gateway Timeout ... Wenn ich jedoch mywebsite.com:8001 lade, wird die Anwendung wie erwartet geladen!

Etwas hindert Nginx also daran, mit dem Upstream-Server zu kommunizieren.

All dies begann, nachdem meine Hosting-Firma den Computer zurückgesetzt hatte, auf dem meine Sachen liefen, bevor es überhaupt keine Probleme gab.

Hier ist mein vhosts-Serverblock:

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;
    }
} 

Und die Ausgabe aus meinem Nginx-Fehlerprotokoll:

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"
Dave Roma
quelle
Läuft auf dem Server SELinux?
CrackerJack9
In meinem Fall war das NAT-Gateway das Problem, nicht die NGINX- oder die Backend-API. stackoverflow.com/a/62351959/9956279
Sushilinux

Antworten:

151

Kann wahrscheinlich ein paar weitere Zeilen hinzufügen, um die Zeitüberschreitung für den Upstream zu verlängern. In den folgenden Beispielen wird das Zeitlimit auf 300 Sekunden festgelegt:

proxy_connect_timeout       300;
proxy_send_timeout          300;
proxy_read_timeout          300;
send_timeout                300;
user2540984
quelle
5
Ich denke, dass das Erhöhen des Timeouts selten die Antwort ist, es sei denn, Sie wissen, dass Ihr Netzwerk / Dienst immer oder in einigen Fällen sehr langsam reagiert. Heutzutage sollten nur wenige Webanfragen länger als ein paar Sekunden dauern, es sei denn, Sie laden Inhalte (Dateien / Bilder) herunter
Almund,
@Almund Ich dachte das Gleiche (hätte mich fast nicht darum gekümmert), aber aus irgendeinem Grund hat das nur für mich funktioniert. (Früher nach 60 Sekunden abgelaufen, jetzt sofort eine Antwort erhalten).
Dax Fohl
@Dax Fohl: Das ist merkwürdig. Ich habe die Quelle heruntergezogen und einen kurzen Blick darauf geworfen. Nach allem, was ich sehen kann, werden durch Festlegen einer Proxy-Einstellung neben dem Proxy-Pass eine Reihe von Einstellungen initialisiert, von denen ich annehme, dass sie den Proxy auf eine andere Weise ausführen Verhalten.
Almund
Habe das Problem für mich mit einem NodeJS-Server nicht gelöst
vpx
3
Ich finde, dass ich das nur proxy_read_timeoutbeim Debuggen im Backend brauche . Vielen Dank!
Jeff Puckett
79

Durch Erhöhen des Zeitlimits wird Ihr Problem wahrscheinlich nicht gelöst, da der tatsächliche Zielwebserver, wie Sie sagen, einwandfrei reagiert.

Ich hatte das gleiche Problem und stellte fest, dass es damit zu tun hatte, dass für die Verbindung kein Keep-Alive verwendet wurde. Ich kann nicht wirklich antworten, warum dies so ist, aber beim Löschen des Verbindungsheaders habe ich dieses Problem gelöst und die Anfrage wurde einwandfrei weitergeleitet:

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;
    }
}

Schauen Sie sich diese Beiträge an, in denen dies ausführlicher erläutert wird: nginx Upstream-Verbindung nach Anfrage schließen Erläuterung des Keep-Alive-Headers http://nginx.org/en/docs/http/ngx_http_upstream_module.html#keepalive

Almund
quelle
7
MONATE von Problemen, die durch eine einzelne Zeile gelöst wurden proxy_set_header Connection "";lol, verwenden Sie nicht runcloud
nodws
21

user2540984 und viele andere haben darauf hingewiesen, dass Sie versuchen können, Ihre Timeout-Einstellungen zu erhöhen. Ich selbst hatte ein ähnliches Problem wie dieses und versuchte, meine Timeout-Einstellungen in der Datei /etc/nginx/nginx.conf zu ändern , wie fast jeder in diesen Threads vorschlägt. Dies half mir jedoch kein bisschen; Es gab keine offensichtliche Änderung der Timeout-Einstellungen von NGINX. Nach vielen Stunden der Suche gelang es mir endlich, mein Problem zu lösen.

Die Lösung liegt in diesem Forenthread und es heißt, dass Sie Ihre Timeout-Einstellungen in /etc/nginx/conf.d/timeout.conf ablegen sollten (und wenn diese Datei nicht vorhanden ist, sollten Sie sie erstellen). Ich habe die gleichen Einstellungen verwendet, wie im Thread vorgeschlagen:

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

Dies ist möglicherweise nicht die Lösung für Ihr spezielles Problem, aber wenn jemand anderes bemerkt, dass die Zeitüberschreitungsänderungen in /etc/nginx/nginx.conf nichts bewirken , hoffe ich, dass diese Antwort hilft!

Andreas Forslöw
quelle
Hallo, es gibt keine timeout.conf in meinem Verzeichnis config.d. Sie sagten, erstellen Sie es, und ich möchte es bestätigen. Fügen Sie einfach die obige Einstellung in die timeout.conf ein.
tktktk0711
Ja, füge sie einfach hinzu. Sie können sie für Ihre eigenen Bedürfnisse modifizieren, aber diese haben für mich funktioniert!
Andreas Forslöw
Leider funktioniert dies in Laravel Homestead mit Ubuntu und Nginx nicht. :( Wollen Sie nur diese Zeilen hinzufügen? Ohne server{}oder etwas anderes? Dieser Fehler tritt direkt nach 5 Minuten auf. Ich lade neu, starte neu und es kommt nie über diese 5 Minuten oder 300 Sekunden hinaus. Gibt es weitere Ideen, die behoben werden müssen es?
Pathros
15

Wenn Sie das Zeitlimit für alle Websites erhöhen oder hinzufügen möchten, können Sie der nginx.confDatei die folgenden Zeilen hinzufügen .

Fügen Sie dem httpAbschnitt /usr/local/etc/nginx/nginx.confoder der /etc/nginx/nginx.confDatei die folgenden Zeilen hinzu .

fastcgi_read_timeout 600;
proxy_read_timeout 600;

Wenn die obigen Zeilen nicht in der confDatei vorhanden sind, fügen Sie sie hinzu, andernfalls erhöhen Sie sie fastcgi_read_timeoutund proxy_read_timeoutstellen Sie sicher, dass bei nginx und php-fpm keine Zeitüberschreitung aufgetreten ist.

Um das Zeitlimit für nur eine Site zu erhöhen, können Sie in vim bearbeiten /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; 
}

und nachdem Sie diese Zeilen hinzugefügt nginx.confhaben, vergessen Sie nicht, nginx neu zu starten.

service php7-fpm reload 
service nginx reload

oder, wenn Sie Valet verwenden, geben Sie einfach ein valet restart.

Adeel
quelle
1
Danke funktioniert für mich:fastcgi_read_timeout 600; proxy_read_timeout 600;
Alejandro
13

Sie können sich dieser Situation auch stellen, wenn Ihr Upstream-Server einen Domänennamen verwendet und sich seine IP-Adresse ändert (z. B. Ihr Upstream zeigt auf einen AWS Elastic Load Balancer).

Das Problem ist, dass nginx die IP-Adresse einmal auflöst und sie für nachfolgende Anforderungen zwischengespeichert lässt, bis die Konfiguration neu geladen wird.

Sie können nginx anweisen, einen Nameserver zu verwenden, um die Domäne nach Ablauf des zwischengespeicherten Eintrags erneut aufzulösen :

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;
}

Die Dokumente auf proxy_pass erklären, warum dieser Trick funktioniert:

Der Parameterwert kann Variablen enthalten. Wenn in diesem Fall eine Adresse als Domänenname angegeben wird, wird der Name unter den beschriebenen Servergruppen gesucht und, falls er nicht gefunden wird, mithilfe eines Resolvers ermittelt.

Ein großes Lob an "Nginx mit dynamischen Upstreams" (tenzer.dk) für die detaillierte Erklärung, die auch einige relevante Informationen zu einer Einschränkung dieses Ansatzes in Bezug auf weitergeleitete URIs enthält.

el.atomo
quelle
1
Diese Antwort ist Gold, genau das, was mir passiert ist. Upstream zeigt auf aws elb und das plötzliche Gateway-Timeout.
Nathan Do
2

Hatte das gleiche Problem. Es stellte sich heraus, dass dies durch die Verfolgung der iptables-Verbindung auf dem Upstream-Server verursacht wurde. Nach dem Entfernen --state NEW,ESTABLISHED,RELATEDaus dem Firewall-Skript und dem Leeren mit conntrack -Fdem Problem war weg.

mindlab
quelle
0

NGINX selbst ist möglicherweise nicht die Hauptursache.

IF „Mindest Ports pro VM - Instanz“ Set auf dem NAT - Gateway - die zwischen Ihrer NGINX Instanz & dem Stand proxy_passZiel - für die Anzahl der gleichzeitigen Anforderungen zu klein ist, hat es erhöht werden.

Lösung: Erhöhen Sie die verfügbare Anzahl von Ports pro VM auf NAT Gateway.

Kontext In meinem Fall wurde in Google Cloud ein Reverse-Proxy-NGINX in einem Subnetz mit einem NAT-Gateway platziert. Die NGINX-Instanz leitete Anforderungen über das NAT-Gateway an eine Domäne um, die unserer Backend-API (Upstream) zugeordnet ist.

Diese Dokumentation von GCP hilft Ihnen zu verstehen, wie wichtig NAT für das NGINX 504-Timeout ist.

Sushilinux
quelle
-1

In meinem Fall starte ich PHP neu und es wird ok.

Mahdy Aslamy
quelle