Saya mencoba mengatur nginx sebagai proxy terbalik, dengan sejumlah besar server backend. Saya ingin memulai backend on-demand (berdasarkan permintaan pertama yang masuk), jadi saya memiliki proses kontrol (dikendalikan oleh permintaan HTTP) yang memulai backend tergantung pada permintaan yang diterimanya.
Masalah saya adalah mengkonfigurasi nginx untuk melakukannya. Inilah yang saya miliki sejauh ini:
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;
}
}
Ini tidak berfungsi - nginx tampaknya mengabaikan kode status apa pun yang dikembalikan dari server kontrol. Tidak ada error_page
arahan di @handle_502
lokasi yang berfungsi, dan kode 451 akan dikirim apa adanya ke klien.
Saya menyerah mencoba menggunakan redirection nginx internal untuk ini, dan mencoba memodifikasi server kontrol untuk memancarkan 307 redirect ke lokasi yang sama (sehingga klien akan mencoba kembali permintaan yang sama, tetapi sekarang dengan server backend memulai). Namun, sekarang nginx dengan bodohnya menimpa kode status dengan kode yang didapatnya dari upaya permintaan backend (502), meskipun server kontrol mengirim header "Lokasi". Saya akhirnya "bekerja" dengan mengubah baris error_page menjadierror_page 502 =307 @handle_502;
, sehingga memaksa semua balasan server kontrol untuk dikirim kembali ke klien dengan kode 307. Ini sangat hacky dan tidak diinginkan, karena 1) tidak ada kontrol atas apa yang harus dilakukan nginx selanjutnya tergantung pada respon server kontrol (idealnya kami hanya ingin mencoba kembali backend hanya jika server kontrol melaporkan keberhasilan), dan 2) tidak semua HTTP klien mendukung pengalihan HTTP (mis. pengguna curl dan aplikasi yang menggunakan libcurl perlu mengaktifkan pengalihan berikut secara eksplisit).
Apa cara yang tepat untuk mendapatkan nginx untuk mencoba proksi ke server hulu A, lalu B, lalu A lagi (idealnya, hanya ketika B mengembalikan kode status tertentu)?
proxy_next_upstream
triknya (skenario saya tidak serumit milik Anda), saya hanya ingin nginx untuk mencoba server berikutnya jika ada kesalahan, jadi saya harus menambahkanproxy_next_upstream error timeout invalid_header non_idempotent;
(non_idempotent
, karena saya ingin meneruskanPOST
permintaan).Anda dapat mencoba sesuatu seperti yang berikut ini
sumber
a.example.net
setelah gagal sekali pada permintaan yang sama. Ini akan mengirim ke klien kesalahan yang ditemui ketika mencoba terhubungb.example.net
, yang tidak akan menjadi apa yang mereka harapkan kecuali saya akan mengimplementasikan proxy di server kontrol juga.