ฉันกำลังพยายามตั้งค่า 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การร้องขอเป็นหลัก)