ฉันกำลังพยายามตั้งค่า nginx เป็น reverse proxy พร้อมเซิร์ฟเวอร์ backend จำนวนมาก ฉันต้องการเริ่มต้นแบ็กเอนด์ตามคำขอ (ตามคำขอแรกที่เข้ามา) ดังนั้นฉันจึงมีกระบวนการควบคุม (ควบคุมโดยคำขอ HTTP) ซึ่งเริ่มต้นแบ็กเอนด์ขึ้นอยู่กับคำขอที่ได้รับ
ปัญหาของฉันคือการกำหนดค่า nginx ให้ทำ นี่คือสิ่งที่ฉันมี:
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;
}
}
วิธีนี้ใช้ไม่ได้ดูเหมือนว่า nginx จะไม่สนใจรหัสสถานะใด ๆ ที่ส่งคืนจากเซิร์ฟเวอร์ควบคุม ไม่มีerror_page
คำสั่งในการ@handle_502
ทำงานในสถานที่และรหัส 451 ได้รับการส่งไปยังลูกค้า
ฉันเลิกพยายามใช้การเปลี่ยนเส้นทาง nginx ภายในสำหรับเรื่องนี้และพยายามแก้ไขเซิร์ฟเวอร์ควบคุมเพื่อปล่อยการเปลี่ยนเส้นทาง 307 ไปยังตำแหน่งเดียวกัน (เพื่อให้ลูกค้าจะลองคำขอเดียวกันอีกครั้ง แต่ตอนนี้เริ่มต้นเซิร์ฟเวอร์แบ็กเอนด์) อย่างไรก็ตามตอนนี้ nginx กำลังเขียนทับรหัสสถานะอย่างโง่เขลาด้วยรหัสที่ได้จากการพยายามแบ็กเอนด์ (502) แม้ว่าเซิร์ฟเวอร์ควบคุมจะส่งส่วนหัว "ตำแหน่ง" ในที่สุดฉันก็ได้ "ทำงาน" โดยเปลี่ยนบรรทัด error_page เป็นerror_page 502 =307 @handle_502;
ดังนั้นบังคับให้เซิร์ฟเวอร์ควบคุมทั้งหมดตอบกลับถูกส่งกลับไปยังไคลเอนต์ด้วยรหัส 307 นี่คือแฮ็กและไม่พึงประสงค์เนื่องจาก 1) ไม่มีการควบคุมสิ่งที่ nginx ควรทำต่อไปขึ้นอยู่กับการตอบสนองของเซิร์ฟเวอร์ควบคุม (โดยเฉพาะอย่างยิ่งเราต้องการลองแบ็กเอนด์เฉพาะในกรณีที่เซิร์ฟเวอร์ควบคุมรายงานว่าสำเร็จ) และ 2) ไม่ใช่ HTTP ทั้งหมด ไคลเอนต์รองรับการเปลี่ยนเส้นทาง HTTP (เช่นผู้ใช้ curl และแอปพลิเคชันที่ใช้ libcurl ต้องเปิดใช้งานการเปลี่ยนเส้นทางต่อไปนี้อย่างชัดเจน)
วิธีที่ถูกต้องในการทำให้ nginx พยายามพร็อกซีไปยังเซิร์ฟเวอร์ upstream A คือ B และจากนั้น A อีกครั้ง (โดยเฉพาะเมื่อ B ส่งคืนรหัสสถานะเฉพาะ)
proxy_next_upstream
แล้วการหลอกลวง (สถานการณ์ของฉันไม่ซับซ้อนเหมือนของคุณ) ฉันแค่อยากให้ nginx ลองเซิร์ฟเวอร์ถัดไปหากมีข้อผิดพลาดเกิดขึ้นดังนั้นฉันจึงต้องเพิ่มproxy_next_upstream error timeout invalid_header non_idempotent;
(non_idempotent
เพราะฉันต้องการส่งต่อPOST
การร้องขอเป็นหลัก)