Ich versuche, Nginx als Reverse-Proxy mit einer großen Anzahl von Back-End-Servern einzurichten. Ich möchte das Backend auf Anforderung starten (bei der ersten eingehenden Anforderung), daher habe ich einen Steuerungsprozess (gesteuert durch HTTP-Anforderungen), der das Backend abhängig von der empfangenen Anforderung startet.
Mein Problem ist die Konfiguration von Nginx, um es zu tun. Folgendes habe ich bisher:
server {
listen 80;
server_name $DOMAINS;
location / {
# redirect to named location
#error_page 418 = @backend;
#return 418; # doesn't work - error_page doesn't work after redirect
try_files /nonexisting-file @backend;
}
location @backend {
proxy_pass http://$BACKEND-IP;
error_page 502 @handle_502; # Backend server down? Try to start it
}
location @handle_502 { # What to do when the backend server is not up
# Ping our control server to start the backend
proxy_pass http://127.0.0.1:82;
# Look at the status codes returned from control server
proxy_intercept_errors on;
# Fallback to error page if control server is down
error_page 502 /fatal_error.html;
# Fallback to error page if control server ran into an error
error_page 503 /fatal_error.html;
# Control server started backend successfully, retry the backend
# Let's use HTTP 451 to communicate a successful backend startup
error_page 451 @backend;
}
location = /fatal_error.html {
# Error page shown when control server is down too
root /home/nginx/www;
internal;
}
}
Dies funktioniert nicht - nginx scheint alle vom Steuerungsserver zurückgegebenen Statuscodes zu ignorieren. Keine der error_page
Direktiven am @handle_502
Standort funktioniert, und der Code 451 wird unverändert an den Client gesendet.
Ich habe aufgehört, die interne Nginx-Umleitung zu verwenden, und habe versucht, den Steuerungsserver so zu ändern, dass eine 307-Umleitung an denselben Speicherort gesendet wird (sodass der Client dieselbe Anforderung erneut versucht, der Back-End-Server jedoch jetzt gestartet wird). Jetzt überschreibt nginx jedoch dummerweise den Statuscode mit dem, den es aus dem Back-End-Anforderungsversuch (502) erhalten hat, obwohl der Steuerungsserver einen "Standort" -Header sendet. Ich habe es schließlich "funktioniert", indem ich die error_page-Zeile in geändert habeerror_page 502 =307 @handle_502;
Dadurch werden alle Antworten des Steuerungsservers gezwungen, mit einem 307-Code an den Client zurückgesendet zu werden. Dies ist sehr schwierig und unerwünscht, da 1) es keine Kontrolle darüber gibt, was Nginx als nächstes tun soll, abhängig von der Antwort des Kontrollservers (im Idealfall möchten wir das Backend nur wiederholen, wenn der Kontrollserver Erfolg meldet), und 2) nicht alles HTTP Clients unterstützen HTTP-Weiterleitungen (z. B. Curl-Benutzer und libcurl-verwendende Anwendungen müssen die folgenden Weiterleitungen explizit aktivieren).
Was ist der richtige Weg, um Nginx zu veranlassen, einen Proxy für Upstream-Server A, dann B und dann wieder A zu erstellen (idealerweise nur, wenn B einen bestimmten Statuscode zurückgibt)?
proxy_next_upstream
der Trick (nun, mein Szenario war nicht so komplex wie deins), ich wollte nur, dass Nginx den nächsten Server ausprobiert, wenn ein Fehler auftritt, also musste ich hinzufügenproxy_next_upstream error timeout invalid_header non_idempotent;
(non_idempotent
weil ich hauptsächlichPOST
Anfragen weiterleiten möchte ).Sie können Folgendes ausprobieren
quelle
a.example.net
es nicht erneut, nachdem es bei derselben Anforderung einmal fehlgeschlagen ist. Es sendet den Fehler, der beim Verbindungsaufbau aufgetreten ist, an den Client.b.example.net
Dies ist nicht der erwartete Fehler , es sei denn, ich implementiere die Proxy-Funktion auch auf dem Steuerungsserver.