我正在尝试将nginx设置为具有大量后端服务器的反向代理。我想按需启动后端(根据传入的第一个请求),因此我有一个控制过程(由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重定向发送到同一位置(以便客户端将重试相同的请求,但现在后端服务器已启动)。然而,尽管控制服务器正在发送“ Location”报头,但是现在nginx愚蠢地用从后端请求尝试获得的状态码覆盖状态码(502)。我最终通过将error_page行更改为“工作”error_page 502 =307 @handle_502;
,从而迫使所有控制服务器回复均以307码发送回客户端。这非常骇人且不受欢迎,因为1)无法根据控制服务器的响应来控制nginx接下来应执行的操作(理想情况下,仅当控制服务器报告成功时,我们才想重试后端),以及2)并非所有HTTP客户端支持HTTP重定向(例如curl用户和使用libcurl的应用程序需要显式启用以下重定向)。
使nginx尝试先代理到上游服务器A,然后再代理B,然后再代理A的正确方法是什么(理想情况下,仅当B返回特定的状态码时)?
proxy_next_upstream
成功的秘诀是(我的情况没有您的复杂),我只是想让nginx在发生错误时尝试下一个服务器,因此我不得不添加proxy_next_upstream error timeout invalid_header non_idempotent;
(non_idempotent
,因为我主要是转发POST
请求)。