Sto cercando di configurare nginx come proxy inverso, con un gran numero di server back-end. Vorrei avviare i back-end su richiesta (sulla prima richiesta che arriva), quindi ho un processo di controllo (controllato da richieste HTTP) che avvia il back-end a seconda della richiesta che riceve.
Il mio problema è configurare nginx per farlo. Ecco cosa ho finora:
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;
}
}
Questo non funziona: sembra che nginx ignori qualsiasi codice di stato restituito dal server di controllo. Nessuna delle error_page
direttive nella @handle_502
posizione funziona e il codice 451 viene inviato così com'è al client.
Ho rinunciato a provare a utilizzare il reindirizzamento interno nginx per questo, e ho provato a modificare il server di controllo per emettere un reindirizzamento 307 nella stessa posizione (in modo che il client potesse ritentare la stessa richiesta, ma ora con il server back-end avviato). Tuttavia, ora nginx sta sovrascrivendo stupidamente il codice di stato con quello ottenuto dal tentativo di richiesta back-end (502), nonostante il server di controllo stia inviando un'intestazione "Posizione". Finalmente ho ottenuto "funzionante" modificando la riga error_page inerror_page 502 =307 @handle_502;
, costringendo così tutte le risposte del server di controllo a essere rinviate al client con un codice 307. Questo è molto caotico e indesiderabile, perché 1) non c'è controllo su ciò che nginx dovrebbe fare in seguito alla risposta del server di controllo (idealmente vogliamo riprovare il back-end solo se il server di controllo riporta il successo), e 2) non tutto HTTP i client supportano i reindirizzamenti HTTP (ad esempio, gli utenti arricciati e le applicazioni che usano libcurl devono abilitare esplicitamente i seguenti reindirizzamenti).
Qual è il modo corretto per ottenere nginx per tentare di eseguire il proxy al server upstream A, quindi B, quindi di nuovo A (idealmente, solo quando B restituisce un codice di stato specifico)?
proxy_next_upstream
fatto il trucco (beh, il mio scenario non era complesso come il tuo), volevo solo nginx per provare il server successivo in caso di errore, quindi ho dovuto aggiungereproxy_next_upstream error timeout invalid_header non_idempotent;
(non_idempotent
, perché voglio inoltrare principalmente lePOST
richieste).