Назад | Перейти на главную страницу

Перезагрузка новой конфигурации Nginx без простоев

У меня есть сервер Nginx, который постоянно обрабатывает большое количество запросов. Я хочу иметь возможность изменять файл конфигурации сервера и динамически перезагружать его без простоев.

Я запускаю в оболочке следующую строку:

httperf --server=127.0.0.1 --port=80 --uri=/ --num-conns=1 --num-calls=10

И пока он отправляет запросы, я перезагружаю свою конфигурацию nginx. Я пробовал два следующих варианта:

sudo nginx -s reload

sudo kill -s HUP [pid]

Оба они заставляют httperf возвращать некоторые ошибки. В среднем после двух хороших запросов httperf завершает работу и выводит журнал со следующей соответствующей строкой:

Errors: total 1 client-timo 0 socket-timo 0 connrefused 0 connreset 1

Я читал во многих местах, что перезагрузка должна выполняться плавно, без простоев, но из теста, который я запускаю, все кажется другим.

Мои вопросы:

  1. Я неправильно провожу тесты? Почему я получаю сброс этого соединения?
  2. Есть решение этой проблемы?
  3. Мне действительно нужен балансировщик нагрузки, который я могу динамически добавлять и удалять с него серверы, какие-либо лучшие решения, которые подходят для моей проблемы?

Заранее благодарим за помощь, с нетерпением жду проницательных ответов.

Чтобы понять следующий ответ, требуется некоторая предыстория:

Я неправильно провожу тесты?

Да, вы несколько неправильно выполняете тест. Проблема в том, что ваш тест использует ПОСТОЯННОЕ соединение для отправки 10 запросов. Вы можете легко проверить это, выполнив следующий тест, и у вас не будет сбоев соединения (потому что вы отправляете только один запрос на соединение):

httperf --server=127.0.0.1 --port=80 --uri=/ --num-conns=10 --num-calls=1

Почему я получаю сброс этого соединения?

Если вы посмотрите на документация nginx, вы найдете это:

Старые рабочие процессы, получив команду на завершение работы, перестают принимать новые соединения и продолжают обслуживать текущие запросы, пока все такие запросы не будут обслужены. После этого старые рабочие процессы завершаются.

Это правда, но в документации не упоминается, что происходит с постоянными соединениями. Я нашел ответ в старом список рассылки. После того, как текущий текущий запрос будет обработан, nginx инициирует закрытие постоянного соединения, отправив [FIN, ACK] клиенту.

Чтобы проверить это, я использовал WireShark и настроил сервер с одним простым рабочим, который по запросу спит 5 секунд, а затем отвечает. Я использовал следующую команду для отправки запроса:

httperf --server=127.0.0.1 --port=80 --uri=/ --num-conns=1 --num-calls=2

После выполнения ранее упомянутой команды я перезагрузил nginx (пока он обрабатывал первый запрос). Вот пакеты, обнаруженные WireShark:

  • 3892-3894 - обычное установление TCP-соединения.
  • 3895 - клиент отправил первый запрос.
  • 3896 - сервер подтверждает 3895.
  • Вот nginx reload был выполнен.
  • 4089 - сервер отправил ответ.
  • 4090 - сервер отправил сигнал закрытия соединения.
  • 4091 - клиент подтверждает 4089.
  • 4092 - клиент подтверждает 4090.
  • 4093 - клиент отправил второй запрос (Какого черта?)
  • 4094 - клиент отправил сигнал закрытия соединения.
  • 4095 - сервер подтверждает 4093.
  • 4096 - сервер подтверждает 4094.

Все в порядке, этот сервер не отправил никакого ответа на второй запрос. В соответствии с Завершение TCP-соединения:

Сторона, которая завершила работу, больше не может отправлять данные в соединение, но другая сторона может. Завершающая сторона должна продолжать считывать данные, пока другая сторона также не завершится.

Следующий вопрос: почему 4093 произошло после того, как клиент получил сигнал о закрытии соединения с сервера?

Наверное, это ответ:

Я бы сказал, что POST происходит одновременно с FIN, то есть клиент отправил POST, потому что его стек TCP еще не обработал FIN с сервера. Обратите внимание, что захват пакетов выполняется до обработки данных системой.

Я не могу это комментировать, так как я не специалист в области нетворкинга. Может быть, кто-нибудь еще может дать более содержательный ответ, почему был отправлен второй запрос.

UPD Связанный ранее вопрос не актуален. Спросил отдельный вопрос о проблеме.

Есть решение этой проблемы?

Как упоминалось в список рассылки:

Клиенты HTTP / 1.1 должны обрабатывать закрытие соединения keepalive, так что это не должно быть проблемой.

Я думаю, что это нужно делать на стороне клиента. И если соединение закрывается сервером, клиент должен открыть новое соединение и повторить запрос.

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

Я не знаю о других серверах, поэтому не могу давать здесь советы.

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