У меня есть сервер 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
Я читал во многих местах, что перезагрузка должна выполняться плавно, без простоев, но из теста, который я запускаю, все кажется другим.
Мои вопросы:
Заранее благодарим за помощь, с нетерпением жду проницательных ответов.
Чтобы понять следующий ответ, требуется некоторая предыстория:
Я неправильно провожу тесты?
Да, вы несколько неправильно выполняете тест. Проблема в том, что ваш тест использует ПОСТОЯННОЕ соединение для отправки 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:
nginx reload
был выполнен.Все в порядке, этот сервер не отправил никакого ответа на второй запрос. В соответствии с Завершение TCP-соединения:
Сторона, которая завершила работу, больше не может отправлять данные в соединение, но другая сторона может. Завершающая сторона должна продолжать считывать данные, пока другая сторона также не завершится.
Следующий вопрос: почему 4093 произошло после того, как клиент получил сигнал о закрытии соединения с сервера?
Наверное, это ответ:
Я бы сказал, что POST происходит одновременно с FIN, то есть клиент отправил POST, потому что его стек TCP еще не обработал FIN с сервера. Обратите внимание, что захват пакетов выполняется до обработки данных системой.
Я не могу это комментировать, так как я не специалист в области нетворкинга. Может быть, кто-нибудь еще может дать более содержательный ответ, почему был отправлен второй запрос.
UPD Связанный ранее вопрос не актуален. Спросил отдельный вопрос о проблеме.
Есть решение этой проблемы?
Как упоминалось в список рассылки:
Клиенты HTTP / 1.1 должны обрабатывать закрытие соединения keepalive, так что это не должно быть проблемой.
Я думаю, что это нужно делать на стороне клиента. И если соединение закрывается сервером, клиент должен открыть новое соединение и повторить запрос.
Мне действительно нужен балансировщик нагрузки, который я могу динамически добавлять и удалять с него серверы, какие-либо лучшие решения, которые подходят для моей проблемы?
Я не знаю о других серверах, поэтому не могу давать здесь советы.
Как только ваши клиенты смогут правильно обрабатывать закрытие соединения, не должно быть никаких причин, мешающих вам использовать nginx.