Wie kann ich verhindern, dass nginx PUT- oder POST-Anforderungen bei einem Timeout des Upstream-Servers erneut versucht?


11

Wir verwenden nginx, um Ausgleichsanforderungen in unsere Anwendung zu laden. Wir haben festgestellt, dass nginx zu einem anderen Upstream-Server wechselt, wenn bei Anfragen eine Zeitüberschreitung auftritt (gut). Dies gilt jedoch für PUT- und POST-Anforderungen, die zu unerwünschten Ergebnissen führen können (Daten werden zweimal gespeichert). Ist es möglich, nginx so zu konfigurieren, dass GET-Anforderungen nur bei Zeitüberschreitung wiederholt werden? Oder gibt es einen anderen Weg, um das Problem zu lösen?

Unsere Konfiguration ist wie folgt:

upstream mash {
    ip_hash;
    server 127.0.0.1:8081;
    server 192.168.0.11:8081;
}

server {
    ...
    location / {
        proxy_pass http://mash/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;        
    }
}

Antworten:


8

Es ist seit Version 1.9.13 zum Standardverhalten geworden

Um es manuell zurück zu ändern, können Sie verwenden:

proxy_next_upstream error timeout non_idempotent;

6

Ich weiß, dass ich ziemlich spät zum Spiel komme, aber für mich ist dies das beste Ergebnis bei der Suche nach diesem Problem, deshalb wollte ich meine Lösung teilen.

Dies verwendet die if-Direktive (mit einem der wenigen gültigen Anwendungsfälle ) in Kombination mit dem benutzerdefinierten Fehlerbehandler :

upstream backend {
    server backend1;
    server backend2;
}

server {
    server_name proxy;

    location / {
        error_page 598 = @retry;
        error_page 599 = @no_retry;
        if ($request_method = POST) {
            return 599;
        }
        return 598;
    }

    location @retry {
        proxy_pass http://backend;
    }

    location @no_retry {
        proxy_pass http://backend;
        proxy_next_upstream off;
    }
}

4

Das Dokument finden Sie hier: proxy_next_upstream

Bitte beachten Sie, dass dies ein ungetesteter Kern ist

https://gist.github.com/wojons/6154645


Eigentlich hat es nicht funktioniert: Nginx sagt "proxy_next_upstream hier nicht erlaubt". Ich habe versucht, die if-Blöcke an ihren Platz zu verschieben, und habe den gleichen Fehler erhalten. Die Verwendung von "proxy_next_upstream error" an beiden Standorten funktioniert für sich.
David Tinker

Das ist sehr seltsam, da die Dokumentation eindeutig besagt, dass es im Standortkontext funktioniert
WojonsTech

Es scheint das if (...) {} um proxy_next_upstream zu sein, das nginx nicht mag
David Tinker

Hat jemand das getestet? 4 Upvotes, aber es scheint hier nicht den gültigen Anwendungsfällen zu entsprechen: nginx.com/resources/wiki/start/topics/depth/ifisevil
EoghanM

0

2
Es wird allgemein empfohlen, die nützlichen Informationen aus einem Link in Ihre Antwort aufzunehmen, sodass der Link nicht explizit als nützlich erachtet wird
BE77Y

1
Willkommen bei Server Fault! Während dies theoretisch die Frage beantworten kann, wäre es vorzuziehen , die wesentlichen Teile der Antwort hier aufzunehmen und den Link als Referenz bereitzustellen.
Mark Henderson

-1

Ich habe das gleiche Problem in meinem Tomcat-Server. Proxy-Timeout bei langer Anforderung. Ich habe mein Problem mit proxy_read_timeout gelöst. Wenn das Timeout erhöht wird, ist meine Anfrage nie abgelaufen und es ist kein Problem aufgetreten. Standardzeitüberschreitung 60s. Referenz

location / {
    proxy_pass  http://xxxxxxxxxx.com;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header Host $http_host;
            proxy_set_header X-Forwarded-Proto https;
            proxy_redirect off;
            proxy_connect_timeout      800;
            proxy_send_timeout         800;
            proxy_read_timeout         240;     
}

1
Dies beantwortet die Frage überhaupt nicht. Ihre Probleme sind nicht gleich.
Sven
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.