Базово:
systemctl restart nginx - по сути делает stop → start. То есть Nginx Master процесс получает сигнал SIGTERM, что приводит к моментальному убийству всех воркеров. Клиенты активных на момент рестарта соединений получают ошибки Connection reset
nginx -s reload в свою очередь отправляет Master процессу сигнал SIGHUP. Nginx Не убивает Master и его Worker-процессы, а стартует новый Master с новой конфигурацией, который начинает обрабатывать все новые соединения. Старые процессы завершаются только после обработки всех актичных соединений (graceful shutdown). Но самое интересно происходит на "пограничных" ситуациях.
Что будет происходить, если у вас есть запросы с долгими (условно вечными) соединениями? (websocket? gRPC?)
А если у вас часто изменяется конфигурация и часто выполняется reload?
А будет следующее:
1. Старые воркеры не завершатся, пока клиенты не закроют соединения.
2. Будут запускаться новые воркеры с обновлённым конфигом.
3. Итог: В системе теперь два набора воркеров — старые (с висящими соединениями) и новые (для новых запросов).
А если делать
reload каждую минуту? Через час у вас будет 60 наборов воркеров, жрущих память и CPU. Красота)Возможные решения:
1. Настроить пару параметров для обработки долгих соединений:
proxy_read_timeout 1h; # Закрывать соединение, если данные не приходят час.
keepalive_timeout 10m; # Не давайте соединениям висеть сутками.
2. Если обрывы долгих соединений приводят к проблемам в эксплуатации - это на 99.9% проблема кода и обработки разрыва соединений.
3. Если вам действительно нужно часто делать reload возможно стоит вынести изменяемые параметры в Lua
4. Возможно стоит отказаться от nginx в пользу условного Envoy, но таким образом решая проблему обрыва долгих соединений вы создаете себе огромную кучу других проблем)
Почитать подробнее про обработку Nginx'ом различных сигналов можно ТУТ
#nginx #zvlb_article