# теория · шаг 2 из 4
nginx -t и reload: как не уронить прод
Коротко
Правило одной строкой: nginx -t && systemctl reload nginx. Сначала проверка,
применение только если она прошла.
reloadне перезапускает nginx: мастер поднимает новых воркеров, а старым даёт доработать текущие запросы. Ни одно соединение не рвётся.- Сломанный конфиг
reloadпросто не применит - сайт продолжит работать на старом. А вотrestartпопробует стартовать, упадёт и оставит сайт лежать. reloadперечитывает конфиг целиком, вместе с именами бэкендов; чего он не делает - так это не чистит кеш и не сбрасывает состояние лимитов.- Полный перезапуск нужен редко: смена
user, обновление бинарника.
Если разница reload и restart очевидна - листай до «Теперь сам».
Что будет с тем, кто качает большой файл
Клиент прямо сейчас скачивает архив на два гигабайта, скачано двести мегабайт. В этот момент администратор применяет новый конфиг:
nginx -t && systemctl reload nginx
Что произойдёт со скачиванием: оборвётся, начнётся заново или продолжится?
Продолжится, и докачается до конца - причём по СТАРОМУ конфигу. Почему так и чем за это платят, разберём ниже.
На что это похоже
Пересменка диспетчеров на вокзале.
Новая смена приходит и садится за свободные пульты - все новые вызовы идут уже к ним, по новым инструкциям. Старая смена при этом не встаёт и не бросает трубки: каждый доводит свой разговор до конца и только потом уходит домой.
Какое-то время за пультами сидят обе смены сразу, и работают они по разным инструкциям. Это не сбой, это и есть механизм: пассажир, которому уже начали отвечать, дослушает ответ до конца.
restart - это другое. Это «всем встать и выйти, новая смена придёт через
минуту».
Механизм: что делает reload по шагам
- Мастер читает новый конфиг. Если тот сломан - не происходит ничего: старые воркеры продолжают работать со старым конфигом, сайт жив.
- Конфиг в порядке - мастер поднимает новых воркеров с новыми настройками и передаёт им слушающие сокеты.
- Старым воркерам мастер говорит: новых соединений не принимать, доработать текущие и завершиться.
Правило
Всегда nginx -t && systemctl reload nginx, одной строкой через &&.
Проверка стоит секунду и снимает целый класс инцидентов.
Полный перезапуск нужен редко: смена user, обновление самого бинарника,
в некоторых сборках - изменение worker_processes. Всё остальное - новые
сайты, сертификаты, маршрутизация - применяется через reload.
Разбор: что видно в ps во время reload
Применили конфиг и сразу посмотрели на процессы:
ps -o pid,stat,cmd -C nginx
PID STAT CMD
1234 Ss nginx: master process /usr/sbin/nginx
4501 S nginx: worker process
4502 S nginx: worker process
1236 S nginx: worker process is shutting down
1237 S nginx: worker process is shutting down
Два новых воркера и два старых с пометкой is shutting down. Это норма в
первые секунды после reload.
Ненормально, если такие процессы висят часами. Значит на них остались живые
соединения, и чаще всего это либо длинные загрузки, либо WebSocket, либо
keepalive-соединения, которые клиент не закрывает.
По умолчанию мастер ждёт их бесконечно. Ограничить ожидание можно явно:
worker_shutdown_timeout 30s;
Тогда через тридцать секунд старые воркеры закроют что осталось и уйдут. Подробный разбор этого поведения - в разделе про эксплуатацию; здесь важно знать, что бесконечное ожидание - это умолчание, а не поломка.
Разбор: чего reload не делает
Из механизма легко унести «reload перечитывает всё». Он перечитывает конфиг - и только его. Три вещи, которые остаются как были.
DNS перерезолвится, но только в этот момент. Имена бэкендов разрешаются при
загрузке конфига - и на старте, и на каждом reload. Проверено на стенде:
контейнер переехал на новый адрес, без перезагрузки nginx отдавал 502, после
reload - 200 с нового адреса. А вот САМ по себе, между перезагрузками, nginx
имя не спрашивает никогда: переехал контейнер - и до ближайшего reload трафик
идёт в никуда. Лечится это resolve у сервера группы, разбор в восьмом
разделе.
Кеш не чистится. Ответы, сложенные в proxy_cacheРазбирается в разделе 11, глава «Кеширование ответов бэкенда»: Как устроен кеш nginx (кеш ответов бэкенда), переживают reload
целиком.
Состояние лимитов не сбрасывается. Счётчики limit_reqРазбирается в разделе 12, глава «limit_req и limit_conn»: Как nginx считает частоту и limit_conn (ограничители частоты и числа соединений) живут
в разделяемой памяти и продолжают считать.
И отдельно про рапорт об успехе: systemctl reload nginx в некоторых системах
завершается успешно просто потому, что успешно послал сигнал. Что мастер решил
дальше, systemd уже не знает. Поэтому проверка идёт до, а не после - и поэтому
после применения стоит посмотреть в error_log.
Что ломается без этого
«Сделал restart, и сайт лёг на пять минут». Конфиг был сломан. reload
отказался бы применять его молча и безопасно, restart попробовал стартовать
и не смог.
«Старые воркеры висят вторые сутки». На них остались долгие соединения, а
worker_shutdown_timeout не задан. Память при этом занята двумя поколениями
воркеров сразу.
«Перевыпустили сертификат, reload сделали, браузер показывает старый».
Скорее всего, reload применился не туда: сертификат прописан в другом
server-блоке или файл перезаписан после команды. Проверяется
nginx -T | grep ssl_certificate и датой файла.
Зачем это в работе
Первое - выкладка на живом сервере. Пять команд, тридцать секунд, и правка уезжает без единого потерянного запроса:
nginx -t # синтаксис в порядке?
nginx -T | grep server_name # то ли я вообще правлю?
systemctl reload nginx # применить
curl -sI https://shop.local # проверить, что жив
tail -f /var/log/nginx/error.log # и посмотреть, не ругается ли
Второе - автоматика. В любом сценарии выкладки строка обязана быть именно
nginx -t && systemctl reload nginx: без && скрипт бодро применит сломанный
конфиг там, где человек бы остановился.
Теперь сам
В docker-compose сертификат обновляется по расписанию, после чего запускается
docker exec nginx nginx -s reload. Однажды утром сайт отдаёт ошибку
сертификата, хотя новый файл на месте и reload в логах прошёл. Что стоит
проверить первым и почему reload мог не помочь?
Ответ. Первым - какой файл nginx считает своим: nginx -T | grep
ssl_certificate и дату этого файла. Типичных причин две. Либо сертификат
обновился по другому пути (симлинк live/ перевесили, а в конфиге прописан
конкретный файл из archive/), и тогда reload честно перечитал старый.
Либо reload выполнился РАНЬШЕ, чем скрипт дописал новый файл, - и тогда
достаточно повторить его руками. Оба случая разводятся одной проверкой: путь из
собранного конфига плюс ls -l по этому пути.
Главное
reload поднимает новых воркеров и даёт старым доработать - поэтому ни одно
соединение не рвётся, а сломанный конфиг просто не применяется. restart
такой страховки не даёт. Перечитывается только конфиг: кеш и счётчики лимитов
остаются прежними, а имена бэкендов как раз спрашиваются заново. Пишем всегда
одной строкой через &&.
Комментарии
Пока нет комментариев. Будь первым!
Оставить комментарий