Я пытаюсь настроить 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 в то же место (чтобы клиент повторил тот же запрос, но теперь с запущенным внутренним сервером). Однако теперь nginx тупо перезаписывает код состояния тем, который он получил от попытки запроса бэкенда (502), несмотря на то, что сервер управления отправляет заголовок «Location». Я наконец-то получил его "работать", изменив строку 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
запросы).