Próbuję skonfigurować nginx jako zwrotny serwer proxy z dużą liczbą serwerów zaplecza. Chciałbym uruchomić backendy na żądanie (przy pierwszym przychodzącym żądaniu), więc mam proces kontroli (kontrolowany przez żądania HTTP), który uruchamia backend w zależności od otrzymanego żądania.
Moim problemem jest skonfigurowanie nginx do tego. Oto co mam do tej pory:
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;
}
}
To nie działa - nginx wydaje się ignorować wszelkie kody statusu zwrócone z serwera kontrolnego. Żadna z error_page
dyrektyw w @handle_502
lokalizacji nie działa, a kod 451 jest wysyłany „tak jak jest” do klienta.
Zrezygnowałem z próby użycia do tego wewnętrznego przekierowania nginx i próbowałem zmodyfikować serwer sterujący, aby wysyłał przekierowanie 307 do tej samej lokalizacji (aby klient ponowił to samo żądanie, ale teraz z uruchomionym serwerem zaplecza). Jednak teraz nginx głupio nadpisuje kod statusu kodem otrzymanym z próby żądania zaplecza (502), mimo że serwer sterujący wysyła nagłówek „Lokalizacja”. W końcu „działa”, zmieniając wiersz error_page naerror_page 502 =307 @handle_502;
, zmuszając w ten sposób wszystkie odpowiedzi serwera sterującego do wysłania z powrotem do klienta z kodem 307. Jest to bardzo hackerskie i niepożądane, ponieważ 1) nie ma kontroli nad tym, co nginx powinien zrobić dalej, w zależności od odpowiedzi serwera kontrolnego (idealnie chcemy ponowić próbę zaplecza tylko wtedy, gdy serwer kontrolny zgłasza sukces), i 2) nie wszystkie HTTP klienci obsługują przekierowania HTTP (np. użytkownicy curl i aplikacje korzystające z libcurl muszą wyraźnie włączyć następujące przekierowania).
Jaki jest właściwy sposób, aby nginx spróbował proxy do serwera nadrzędnego A, a następnie B, a następnie A (najlepiej, gdy B zwróci określony kod stanu)?
proxy_next_upstream
zrobiłem lewę (cóż, mój scenariusz nie był tak skomplikowany jak twój), chciałem tylko, aby nginx wypróbował następny serwer, jeśli wystąpił błąd, dlatego musiałem dodaćproxy_next_upstream error timeout invalid_header non_idempotent;
(non_idempotent
, ponieważ chcę głównie przekazywaćPOST
żądania).Możesz spróbować czegoś takiego
źródło
a.example.net
po tym, jak raz zakończy się niepowodzeniem dla tego samego żądania. Wyśle klientowi napotkany błąd podczas próby połączeniab.example.net
, co nie będzie zgodne z oczekiwaniami, chyba że zaimplementuję także proxy na serwerze sterującym.