# теория · шаг 2 из 5
Первые пять минут инцидента
Коротко
Инцидент - плохое время для творчества: работает заранее написанный порядок.
Жив ли процесс → что применено (nginx -T) → свежие строки error_log →
воспроизведение локальным curl → проверка бэкенда напрямую. Смягчать можно
человеческой страницей, протухшим кешем, выводом узла из группы и поднятым
таймаутом - это обезболивание, а не лечение. Режим обслуживания включается
файлом-флагом без перезагрузки конфига, а Retry-After на странице
заглушки требует always - иначе заголовка на 503 не будет.
Свой порядок уже есть - листай до первого разбора: там замеренная заглушка и ловушка с always.
Заглушка на время работ готова: файл-флаг, return 503, своя страница и
Retry-After, чтобы поисковики и клиенты вернулись позже. Проверяешь - страница
на месте, а заголовка нет.
HTTP/1.1 503 Service Temporarily Unavailable
Retry-After: 600
заголовков «X-Without-Always» в ответе: 0
Один заголовок доехал, второй - нет, хотя стоят рядом в одном блоке.
На что это похоже
Первые пять минут инцидента - это не расследование, а сортировка в приёмном покое. Задача не «понять, что случилось», а быстро отделить тяжёлое от лёгкого и понять, чьё это: nginx, приложения или сети.
Отсюда и правило про творчество: у сортировки есть протокол, и он выполняется в одном порядке всегда - именно потому, что в три часа ночи голова работает хуже, чем список.
Механизм: порядок первых пяти минут
Правило
systemctl is-active nginx && ss -ltnp | grep nginx
nginx -T | grep -A5 "server_name shop.local"
tail -n 100 /var/log/nginx/error.log | grep -v "\[notice\]"
curl -sS -o /dev/null -w '%{http_code} %{time_total}\n' -H 'Host: shop.local' http://127.0.0.1/api/cart
curl -sS -o /dev/null -w '%{http_code} %{time_total}\n' http://app:8000/api/cart
Второй шаг стоит отдельного слова: -T печатает собранный конфиг со всеми
include. Половина инцидентов «я же поправил» заканчивается здесь - правка
легла в файл, который не подключён, или её перекрыл другой блок. Третий шаг
тоже: ошибки, начавшиеся ровно в момент жалобы, - твои; всё, что сыплется
неделями, - фон.
Разбор: режим обслуживания файлом-флагом
Заглушку для плановых работ готовят заранее, и включаться она должна без правки конфига:
location / {
if (-f /etc/nginx/maintenance.on) {
return 503;
}
proxy_pass http://app:8000;
}
error_page 503 /maintenance.html;
location = /maintenance.html {
root /var/www/errors;
internal;
add_header Retry-After 600 always;
}
Замер по шагам:
| действие | ответ |
|---|---|
| до включения | 200 |
touch maintenance.on, без reload |
503, тело своей страницы |
заголовок Retry-After с always |
на месте |
соседний заголовок без always |
отсутствует |
rm maintenance.on |
снова 200 |
Два вывода. Первый: if (-f ...) проверяется на каждом запросе, поэтому режим
включается и выключается созданием файла - без reload, без правки конфига,
руками дежурного. Это тот редкий if, который безопасен: внутри только
return (тринадцатый раздел).
Второй - ловушка из крючка. add_header по умолчанию работает только на
успешных кодах, а заглушка - это 503. Без always заголовка на ней не будет,
и клиенты с поисковиками не узнают, когда возвращаться.
Разбор: быстрые смягчения и их цена
Пока чинится причина, стоит перестать делать больно пользователям. Все четыре
приёма применяются через reload и откатываются так же:
| приём | что даёт | чем платишь |
|---|---|---|
error_page 502 503 504 /50x.html |
человеческая страница вместо стандартной | ничем, делай сразу |
proxy_cache_use_stale error timeout http_502 |
отдаём протухшее, пока бэкенд не в себе | часть пользователей видит старые данные |
down у сервера в upstream |
вывести больной узел | оставшиеся берут его нагрузку |
поднять proxy_read_timeout |
дожидаться медленных ответов | соединения живут дольше, слотов меньше |
Последняя строка - причина, по которой это именно обезболивание: поднятый
таймаут удерживает слоты worker_connections, и при затянувшемся инциденте ты
получишь второй, уже свой.
Что ломается без этого
Кручение параметров «на всякий случай». worker_processes,
worker_connections, размеры буферов посреди инцидента менять нельзя: эффект
неочевиден, а отличить его от случайных колебаний в этот момент невозможно.
Если после правки стало лучше - ты не знаешь почему, и это худший из исходов.
Выключенные логи. Соблазн «разгрузить диск» возникает ровно тогда, когда
зрение нужнее всего. Диск чистится ротацией и find -delete по старым файлам,
а не выключением access_log.
Правка, которая никуда не приехала. Классический сценарий: конфиг
поправлен, reload выполнен, ничего не изменилось. Причины две - файл не
подключён (nginx -T покажет) или reload не применился (порт занят, файл
сертификата исчез), а код возврата при этом нулевой, как в первом уроке
раздела. Смотреть надо error_log, а не результат команды.
Зачем это в работе
После инцидента записывают три вещи, пока не забылось. Что сломалось - не
«упал сайт», а «502 на /api/, потому что бэкенд перезапускался дольше своей
готовности». Как узнали - жалоба пользователя или мониторинг, и если
жалоба, то почему не мониторинг. Что заметит раньше в следующий раз.
Для nginx ответ на третий вопрос почти всегда один и тот же: доля 5xx ловит
поломки, 95-й процентиль $upstream_response_time ловит деградацию, число 499
ловит терпение пользователей. Плюс расхождение accepts и handled из
stub_status - оно ловит то, чего в кодах ответа не видно вовсе.
Теперь сам
Ночью дежурный включил режим обслуживания файлом-флагом, утром удалил файл - и
часть пользователей продолжает видеть страницу «идут работы». curl с сервера
отдаёт 200. Что произошло?
Ответ: страницу заглушки закешировали - либо промежуточный кеш и браузер (503
кешируется, если у ответа есть Cache-Control или Expires, а Retry-After
некоторые прокси трактуют как разрешение подождать), либо собственный
proxy_cache, если заглушка попала в него. Проверять: curl -I с сервера и от
пострадавшего, заголовки Cache-Control и Age в ответе, статус
$upstream_cache_status в логе. Лечится добавлением add_header Cache-Control
"no-store" always; на страницу заглушки - на будущее, и сбросом кеша сейчас.
Мораль общая: временная страница обязана быть некешируемой, иначе она
переживёт работы.
Главное
Порядок вместо творчества: жив ли процесс → что применено (nginx -T) →
свежие строки error_log → воспроизведение локальным curl → проверка
бэкенда напрямую тем же путём. Режим обслуживания включается файлом-флагом с
if (-f ...) и return 503 - без перезагрузки конфига, потому что условие
проверяется на каждом запросе; Retry-After на такой странице требует
always, иначе заголовка на 503 не будет (замер: соседний заголовок без
always в ответе отсутствует). Смягчения - своя страница ошибки, протухший
кеш, down у узла и поднятый таймаут - дают время, но последний съедает слоты
соединений. Не крути буферы и воркеров на горячую и не выключай логи. После
инцидента - три вопроса: что сломалось, как узнали, что заметит раньше.
Комментарии
Пока нет комментариев. Будь первым!
Оставить комментарий