Я бы хотел, чтобы Nginx приостанавливал (удерживал) http-запросы на короткие периоды времени, пока я обновляю или перезапускаю серверную службу, выполняю миграцию базы данных или выполняю другие административные задачи, не вызывая ошибок у конечных пользователей.
В основном я бы хотел выполнить следующую последовательность операций:
В идеале это позволило бы мне выполнять административные задачи, требующие монопольного доступа ко всему внутреннему серверу, такие как перезапуски, обновления или миграции, не вызывая у конечных пользователей чего-либо более серьезного, чем задержка, которая, надеюсь, составляет менее минуты.
я нашел это решение, но он не обращается к пункту 2. Более того, ему нужен интерпретатор Lua, скомпилированный в Nginx, с любыми утечками памяти и проблемами безопасности, которые могут возникнуть.
Есть ли какой-нибудь трюк с настройкой или модуль Nginx, специально предназначенный для этой проблемы? Можно ли это сделать с помощью стандартного Nginx, возможно, проверив наличие контрольного файла?
Как другие администраторы решают эту проблему в целом?
(Я знаю, что универсальный и несколько размашистый сервер приложений uWSGI есть эта функция среди сотен других, но я бы предпочел не вводить еще один элемент между Nginx и моим сервером.)
Я предполагаю, что вы выполняете сценарий обслуживания с минимальным временем простоя.
Я бы порекомендовал вам использовать резервный сервер для удержания запроса в течение необходимых секунд <20> (или) даже <100> и перенаправления на исходный URI после перезапуска приложения.
Вы можете следить за потоком ниже nginx, где используется общее решение.
вы можете настроить nginx для выполнения сценария, чтобы массировать и передавать http-вызов некоторому процессу очереди, например beanstalkd, используя обработку ошибок на 502 BAD GATEWAY и / или 503 SERVICE UNAVAILABLE. (ошибка, когда ваша серверная служба недоступна).
затем, после обновления серверной части, извлеките запросы из beanstalkd и обработайте их в своей серверной службе.
Кроме того, если ваша внутренняя служба когда-либо непреднамеренно выйдет из строя, это может удвоиться как решение высокой доступности, чтобы не терять вызовы api. настроить jenkins / cron для автоматической проверки и обработки любой очереди beanstalk.
Я никогда этого не делал, но если бы я когда-нибудь попробовал, думаю, я бы использовал брандмауэр. Мне, вероятно, понадобится сценарий решения, которое будет выглядеть так:
Если шаги 2 + 3 не занимают слишком много времени, клиенты будут повторять попытку и в конечном итоге смогут подключиться на шаге 4. Если они займут слишком много времени, у клиентов будет тайм-аут, но это не проблема, поскольку терпение пользователей время истекло раньше, нет?
У решения есть некоторые уловки. Клиент может получить главную страницу, а затем он не сможет продолжить получение статических файлов (тогда как с учетом ваших задумок, возможно). Однако это не будет проблемой, если вы обслуживаете свои статические файлы с другой машины или CDN.
Кроме того, я считаю, что обычно кто-то будет беспокоиться о том, о чем вы беспокоитесь, только после того, как он уже настроил какое-то решение высокой доступности, например два сервера плюс IP-адрес, который можно перенести с одного сервера на другой. Когда вы перемещаете IP-адрес с одного сервера на другой, пользователи, у которых открыто соединение, отключаются. Я думаю, что это приемлемо, потому что эти пользователи получают что-то вроде пустой страницы в своем браузере, задаются вопросом, что, черт возьми, произошло, нажимают «перезагрузить», на этот раз это работает, и они больше не беспокоятся; они даже не помнят инцидент через несколько минут. Использование уловки с брандмауэром, чтобы избежать этого отключения, создало бы больше проблем, чем решило бы, потому что шаг 2 нужно было бы изменить, чтобы ждать, пока nginx завершит обслуживание запросов к клиентам, а это может занять слишком много времени, если у пользователя медленное соединение. В любом случае, я думаю, что высокая доступность имеет столько проблем, что она получит такой низкий приоритет, что это никогда не будет выполнено (если вы не Google или кто-то еще).
В поисках решения этой проблемы я наткнулся на небольшой репозиторий GitHub под названием бессонница это иллюстрирует простой и элегантный подход с использованием Lua. Предполагая, что у вас установлен модуль Lua, вы сначала захотите включить его в верхней части экрана. nginx.conf
:
load_module /usr/lib/nginx/modules/ndk_http_module.so;
load_module /usr/lib/nginx/modules/ngx_http_lua_module.so;
Затем в вашем http
блок, настройте общую переменную Lua для отслеживания состояния приостановки / возобновления:
http {
lua_shared_dict state 12k;
init_by_lua_block {
ngx.shared.state:set("suspend", false)
}
# rest of your http block
}
Затем в блоке сервера настройте секретное место для сообщения серверу о приостановке / возобновлении:
location = /suspend/MySuperSecretMagicString {
if ($request_method = PUT) {
content_by_lua_block {
ngx.req.read_body()
content = ngx.req.get_body_data()
if (content == "go2sleep") then
ngx.shared.state:set("suspend", true)
else
ngx.shared.state:set("suspend", false)
end
}
}
}
И в вашем основном блоке местоположения добавьте еще один бит Lua:
location / {
access_by_lua_block {
while (ngx.shared.state:get("suspend") == true) do
ngx.sleep(0.2)
end
}
proxy_pass http://my-backend;
}
Теперь вы можете отправить запрос на переход в ждущий режим:
curl -X PUT -d go2sleep http://localhost/suspend/MySuperSecretMagicString
И чтобы выпустить все буферизованные запросы на бэкэнд, просто замените go2sleep
чем-нибудь еще:
curl -X PUT -d UnleashTheHounds http://localhost/suspend/MySuperSecretMagicString
Обратите внимание, что у каждого приостановленного запроса будет свой рабочий, поэтому вам понадобится достаточно worker_connections
справиться с ожидаемым отставанием. Увидеть хранилище бессонницы для дальнейших комментариев и некоторых дополнительных функций. Похожий, но более сложный подход можно найти в Basecamp антракт репозиторий.
Опять же, я не придумал эту технику. Вся заслуга по праву принадлежит пользователю GitHub "solso".
В твоем server
раздел
if ( -f /etc/nginx/sites-enabled/maintenance.ngx ) {
return 503;
}
error_page 503 /maintenance.html
Использовать
# cd /etc/nginx/sites-enabled && mv maintenance.ngx_ maintenance.ngx
и вернуться
# cd /etc/nginx/sites-enabled && mv maintenance.ngx maintenance.ngx_