Как работает перезагрузка NGINX? Почему NGINX не выполняет горячую перезагрузку?

Wei Liu

September 30, 2022

Technology

Недавно я заметил пост на Reddit, в котором говорилось: "Почему NGINX не поддерживает горячую перезагрузку?". Странно, что NGINX, крупнейший в мире веб-сервер, не поддерживает горячую перезагрузку? Значит ли это, что мы все используем nginx -s reload неправильно? С этим вопросом давайте разберемся, как работает перезагрузка NGINX.

Что такое NGINX

NGINX — это кроссплатформенный веб-сервер с открытым исходным кодом, разработанный на языке C. Согласно статистике, среди 1000 сайтов с наибольшим трафиком более 40% используют NGINX для обработки огромного количества запросов.

Почему NGINX так популярен

Какие преимущества есть у NGINX, чтобы обойти другие веб-серверы и сохранять высокий уровень использования?

Основная причина заключается в том, что NGINX разработан для решения проблем высокой нагрузки. Поэтому NGINX может предоставлять стабильный и эффективный сервис, обрабатывая огромное количество одновременных запросов. Более того, по сравнению с конкурентами того же времени, такими как Apache и Tomcat, NGINX имеет множество выдающихся решений, таких как продвинутая событийно-ориентированная архитектура, полностью асинхронный механизм обработки сетевого ввода-вывода и чрезвычайно эффективная система управления памятью. Эти замечательные решения помогают NGINX полностью использовать аппаратные ресурсы серверов и делают его синонимом веб-сервера.

Помимо этого, есть и другие причины:

  1. Высокомодульная архитектура позволяет NGINX иметь множество официальных и сторонних модулей с богатым функционалом.
  2. Свободная лицензия BSD побуждает разработчиков вносить вклад в развитие NGINX.
  3. Поддержка горячей перезагрузки позволяет NGINX предоставлять услуги 24/7.

Среди этих причин горячая перезагрузка является нашей основной темой сегодня.

Что делает горячая перезагрузка

Каковы наши ожидания от горячей перезагрузки? Во-первых, пользователи на стороне клиента не должны замечать перезагрузку сервера. Во-вторых, серверы или вышестоящие сервисы должны динамически загружаться и успешно обрабатывать все запросы пользователей без простоев.

В каких случаях нам нужна горячая перезагрузка? В эпоху Cloud Native микросервисы стали настолько популярными, что все больше сценариев использования требуют частых изменений на стороне сервера. Эти изменения, такие как включение/выключение обратного прокси домена, изменение адресов вышестоящих сервисов и изменение списков разрешенных/запрещенных IP-адресов, связаны с горячей перезагрузкой.

Так как же NGINX реализует горячую перезагрузку?

Принцип горячей перезагрузки NGINX

Когда мы выполняем команду горячей перезагрузки nginx -s reload, она отправляет сигнал HUP мастер-процессу NGINX. Когда мастер-процесс получает сигнал HUP, он последовательно открывает порты для прослушивания и запускает новый рабочий процесс. Таким образом, одновременно будут существовать два рабочих процесса (старый и новый). После того как новый рабочий процесс запустится, мастер-процесс отправит сигнал QUIT старому рабочему процессу для его корректного завершения. Когда старый рабочий процесс получает сигнал QUIT, он сначала закрывает обработчик прослушивания. Теперь все новые соединения будут поступать только в новый рабочий процесс, а сервер завершит старый процесс, как только обработает все оставшиеся соединения.

Теоретически, может ли горячая перезагрузка NGINX полностью соответствовать нашим требованиям? К сожалению, ответ — нет. Какие же недостатки есть у горячей перезагрузки NGINX?

Перезагрузка NGINX вызывает простои

  1. Слишком частая горячая перезагрузка может сделать соединения нестабильными и привести к потере бизнес-данных.

    Когда NGINX выполняет команду перезагрузки, старый рабочий процесс продолжает обрабатывать существующие соединения и автоматически отключается после обработки всех оставшихся запросов. Однако, если клиент не обработал все запросы, он навсегда потеряет бизнес-данные оставшихся запросов. Конечно, это привлечет внимание пользователей на стороне клиента.

  2. В некоторых случаях время завершения старого рабочего процесса занимает так много времени, что это влияет на обычный бизнес.

    Например, когда мы проксируем протокол WebSocket, мы не можем узнать, был ли запрос обработан, потому что NGINX не анализирует заголовочный фрейм. Поэтому, даже если рабочий процесс получает команду завершения от мастер-процесса, он не может завершиться, пока эти соединения не вызовут исключения, не истечет время ожидания или они не отключатся.

    Вот еще один пример: когда NGINX выступает в роли обратного прокси для TCP и UDP, он не может узнать, как часто запрашивается запрос, пока он окончательно не завершится.

    Поэтому старый рабочий процесс обычно занимает много времени, особенно в таких отраслях, как потоковое вещание, медиа и распознавание речи. Иногда время завершения старого рабочего процесса может достигать получаса или даже больше. В то же время, если пользователи часто перезагружают сервер, это создаст множество завершающихся процессов и в конечном итоге приведет к OOM (Out of Memory) в NGINX, что может серьезно повлиять на бизнес.

# всегда существует в старом рабочем процессе: nobody 6246 6241 0 10:51 ? 00:00:00 nginx: worker process nobody 6247 6241 0 10:51 ? 00:00:00 nginx: worker process nobody 6247 6241 0 10:51 ? 00:00:00 nginx: worker process nobody 6248 6241 0 10:51 ? 00:00:00 nginx: worker process nobody 6249 6241 0 10:51 ? 00:00:00 nginx: worker process nobody 7995 10419 0 10:30 ? 00:20:37 nginx: worker process is shutting down <= здесь nobody 7995 10419 0 10:30 ? 00:20:37 nginx: worker process is shutting down nobody 7996 10419 0 10:30 ? 00:20:37 nginx: worker process is shutting down

В итоге, мы можем достичь горячей перезагрузки, выполнив nginx -s reload, что раньше было достаточно. Однако быстрое развитие микросервисов и Cloud Native делает это решение больше не соответствующим требованиям пользователей.

Если частота обновлений вашего бизнеса составляет неделю или день, то эта перезагрузка NGINX все еще может удовлетворить ваши потребности. Однако, что если частота обновлений станет ежечасной или ежеминутной? Например, если у вас есть 100 серверов NGINX, и они перезагружаются раз в час, то потребуется 2400 перезагрузок в день; если сервер перезагружается каждую минуту, то потребуется 8 640 000 перезагрузок в день, что неприемлемо.

Нам нужно решение без переключения процессов, которое также может обеспечить мгновенное обновление контента.

Горячая перезагрузка, которая мгновенно вступает в силу в памяти

Когда появился Apache APISIX, он был разработан для решения проблемы горячей перезагрузки NGINX. APISIX разработан на основе технологического стека NGINX и Lua и представляет собой облачный, высокопроизводительный, полностью динамический микросервисный API-шлюз, использующий etcd в качестве центра конфигурации. Нет необходимости перезагружать сервер для применения новой конфигурации, что означает, что любые изменения вышестоящих сервисов, маршрутов или плагинов не потребуют перезагрузки сервера. Но как APISIX устраняет ограничения NGINX, чтобы достичь идеальной горячей перезагрузки, учитывая, что он разработан на основе технологического стека NGINX?

Сначала давайте посмотрим на архитектуру программного обеспечения Apache APISIX:

Архитектура

APISIX может достичь идеальной горячей перезагрузки, поскольку все конфигурации помещаются в APISIX Core и Plugin Runtime, что позволяет использовать динамические назначения. Например, когда NGINX нужно настроить параметры внутри конфигурационных файлов, каждое изменение вступает в силу только после перезагрузки. Чтобы динамически настраивать маршруты, Apache APISIX настраивает только один конкретный сервер с одним местоположением. Мы должны использовать это местоположение как основной вход, чтобы все запросы сначала проходили через него, а затем APISIX Core динамически назначал бы конкретные вышестоящие сервисы для них. Модуль маршрутов Apache APISIX может поддерживать добавление/удаление, изменение и удаление маршрутов во время работы сервера. Другими словами, он может достичь динамической перезагрузки. Ни одно из этих изменений не привлечет внимание пользователей и не повлияет на обычный бизнес.

Теперь давайте рассмотрим классический сценарий; например, если мы хотим добавить обратный прокси для нового домена, нам нужно только создать вышестоящий сервис в APISIX и добавить новый маршрут. NGINX не нужно перезагружать в этом процессе. Вот еще один пример для системы плагинов: APISIX может использовать плагин IP-restriction для реализации функции списка разрешенных/запрещенных IP-адресов. Все эти обновления функций являются динамическими и не требуют перезагрузки сервера. Благодаря etcd, стратегия конфигурации может достичь мгновенных обновлений с использованием дополнений, и все конфигурации могут вступить в силу немедленно, обеспечивая лучший пользовательский опыт.

Заключение

Горячая перезагрузка NGINX в некоторых случаях приводит к наличию одного старого и одного нового рабочего процесса, что вызывает дополнительное расходование ресурсов. Кроме того, слишком частая горячая перезагрузка может привести к небольшой вероятности полной потери бизнес-данных. В условиях Cloud Native и микросервисов обновления сервисов становятся все более частыми, а стратегии управления API также различаются, что приводит к новым требованиям к горячей перезагрузке.

Горячая перезагрузка NGINX больше не удовлетворяет бизнес-требованиям. Пришло время перейти на Apache APISIX, API-шлюз с более продвинутой стратегией горячей перезагрузки в эпоху Cloud Native. Кроме того, после перехода на APISIX пользователи могут динамически и единообразно управлять API-сервисами, что значительно повышает эффективность управления.

Tags: