У меня есть приложение nodejs, которое всегда работает за nginx. Когда я развертываю новый код, я просто делаю forever restart
но я не могу позволить себе получить 502 даже за такое короткое время.
Как настроить nginx для повторных попыток на этом одном вышестоящем сервере в случае 502? Я пробовал установить proxy_connect_timeout
, proxy_read_timeout
и proxy_send_timeout
например 30s
но я сразу получаю 502 ни на что :(
Конфигурация моего сайта:
upstream my_server {
server 127.0.0.1:3000 fail_timeout=0;
keepalive 1024;
}
server {
listen 3333;
server_name myservername.com;
access_log /var/log/nginx/my_server.log;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
# retry upstream on 502 error
proxy_connect_timeout 30s;
proxy_send_timeout 30s;
proxy_read_timeout 30s;
proxy_pass http://my_server;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_redirect off;
}
}
Можно ли буферизовать запросы на это короткое время, когда апстрим недоступен?
В конечном итоге это звучит как проблема с вашим сервером: nginx отправляет запрос на ваш сервер, соединение сразу же отклоняется, поэтому у nginx нет другого варианта, который мог бы передать ошибку нижестоящему пользователю, поскольку никакой другой восходящий поток не указан, и timeout
значения, которые вы указываете, не играют здесь никакого эффекта, поскольку nginx вообще ничего не должен ждать.
Я не знаю что forever
есть или как это работает, но на ум приходят несколько возможных решений.
Есть две возможности того, что происходит на восходящей стороне:
"Навсегда" может быть принимая соединение и немедленно возвращает ошибку. В этом случае похоже, что вам действительно следует спросить, как заставить его не обрабатывать соединение неправильно, а подождать, пока ваше приложение не завершит развертывание, и обработать запрос тут же. В opengrok
приложение на tomcat
у сервера есть эта проблема.
Никто не слушание на порту, на котором должно работать ваше приложение, поэтому ядро немедленно отбрасывает пакет и сразу же возвращает пакет TCP RST.
Если TCP RST
является причиной, вы можете решить ее, имея forever
сохранить прослушивающий сокет или настроить ядро для постановки входящих пакетов в очередь на определенное время в ожидании того, что кто-то заберет их позже, так что когда forever
действительно запускается, у него будет целая очередь, готовая к обслуживанию.
Настройте ядро так, чтобы оно не выдавалось TCP RST
когда никто не слушает, тогда твой timeout
в nginx будет иметь эффект. Впоследствии настройте nginx
сделать второй запрос другому апстриму.
Если вы обратитесь к одному из вышеперечисленных случаев, все готово.
В противном случае вам нужно попытаться настроить nginx, чтобы исправить проблему:
Вы могли бы попробовать proxy_cache
с участием proxy_cache_use_stale
.
Вы можете попробовать использовать обработчик ошибок: см. proxy_intercept_errors
(вероятно, применяется только в том случае, если 503, который вы получаете, передается из вашего бэкэнда) и error_page
. Вы можете потратить время на обработку ошибок, пока ваше приложение не вернется в исходное состояние, а затем сделать запрос в свое приложение.
sleep()
сколько бы времени ни потребовалось для повторного развертывания вашего приложения, затем либо выполните перенаправление HTTP, либо завершите работу без ответа; черт возьми, вы можете просто реализовать это, попытавшись проксировать TCP-порт, который вы block drop
в брандмауэре, который активирует ваши таймауты в nginx. Впоследствии настройте nginx для выполнения второго запроса.Если вы реализуете один из вышеперечисленных подходов, который включает timeout
активации, то впоследствии потребуется сделать дополнительный запрос к бэкэнду. Вы можете использовать upstream
директиву для этого, где вы либо указываете один и тот же сервер несколько раз, либо, если не принимаете, можете зеркалировать порт через свой брандмауэр, или, что еще лучше, вы могли бы фактически запустить несколько независимых серверов приложений в первую очередь.
Это возвращает нас к вашему серверу приложений: если он не может справиться с проблемой чистого повторного развертывания, возможно, вам следует запустить два таких сервера приложений и использовать nginx для балансировки нагрузки между ними. Или разверните их заново, а затем переключите nginx на новую копию, когда она действительно будет готова. Иначе, как вы могли быть уверены, что ваши клиенты будут готовы ждать ответа от вашего API даже 30 секунд?