Я запускаю экземпляр django за nginx, подключенный с помощью fcgi (с помощью команды run.fcgi manage.py). Поскольку код загружается в память, я не могу перезагрузить новый код, не убивая и не перезапуская процессы django fcgi, тем самым прерывая веб-сайт. Само перезапуск очень быстрый. Но, убив процессы fcgi, некоторые действия некоторых пользователей будут прерваны, что не очень хорошо. Мне интересно, как я могу перезагрузить новый код без каких-либо сбоев. Советы будут высоко оценены!
Как изящно перезапустить django, запускающий fcgi за nginx?
Ответ 1
Я бы начал новый процесс fcgi на новом порту, изменил конфигурацию nginx, чтобы использовать новый порт, имеет конфигурацию перезагрузки nginx (которая сама по себе является изящной), затем в конечном итоге остановит старый процесс (вы можете использовать netstat для поиска когда последнее соединение со старым портом закрыто).
В качестве альтернативы вы можете изменить реализацию fcgi, чтобы развернуть новый процесс, закрыть все сокеты в дочернем элементе, кроме гнезда сервера fcgi, закрыть сокет сервера fcgi в родительском, выполнить новый процесс django в дочернем элементе (что делает его использование серверный сокет fcgi) и завершение родительского процесса после закрытия всех подключений fcgi. IOW, выполнить изящный перезапуск для runfcgi.
Ответ 2
Итак, я пошел вперед и реализовал предложение Мартина. Вот bash script Я придумал.
pid_file=/path/to/pidfile
port_file=/path/to/port_file
old_pid=`cat $pid_file`
if [[ -f $port_file ]]; then
last_port=`cat $port_file`
port_to_use=$(($last_port + 1))
else
port_to_use=8000
fi
# Reset so me don't go up forever
if [[ $port_to_use -gt 8999 ]]; then
port_to_use=8000
fi
sed -i "s/$old_port/$port_to_use/g" /path/to/nginx.conf
python manage.py runfcgi host=127.0.0.1 port=$port_to_use maxchildren=5 maxspare=5 minspare=2 method=prefork pidfile=$pid_file
echo $port_to_use > $port_file
kill -HUP `cat /var/run/nginx.pid`
echo "Sleeping for 5 seconds"
sleep 5s
echo "Killing old processes on $last_port, pid $old_pid"
kill $old_pid
Ответ 3
Я столкнулся с этой страницей, ища решение этой проблемы. Все остальное не удалось, поэтому я обратился к исходному коду:)
Решение кажется намного проще. Сервер Django fcgi использует flup, который правильно обрабатывает сигнал HUP: он отключается, изящно. Итак, все, что вам нужно сделать, это:
-
отправить сигнал HUP на сервер fcgi (полезно использовать аргумент pidfile = для запуска сервера)
-
подождите немного (flup позволяет детям обрабатывать 10 секунд, поэтому подождите еще пару, 15 выглядит как хорошее число)
-
отправил сигнал KILL на сервер fcgi, на всякий случай заблокировал его
-
Запустите сервер снова
Что это.
Ответ 4
Вы можете использовать нереста вместо FastCGI
Ответ 5
Наконец, мы нашли правильное решение этого вопроса.
http://rambleon.usebox.net/post/3279121000/how-to-gracefully-restart-django-running-fastcgi
Сначала отправьте flup сигнал HUP, чтобы подать сигнал на перезагрузку. Затем Flup сделает это для всех своих детей:
- закрывает сокет, который останавливает неактивные дочерние элементы
- отправляет сигнал INT
- ждет 10 секунд
- отправляет сигнал KILL
Когда все дети уйдут, они начнут новые.
Это работает почти все время, за исключением того, что если дочерний элемент обрабатывает запрос, когда flup выполняет шаг 2
, тогда ваш сервер умрет с помощью KeyboardInterrupt
, давая пользователю ошибку 500.
Решение заключается в установке обработчика SIGINT - подробности см. на странице выше. Даже просто игнорирование SIGINT дает вашему процессу 10 секунд для выхода, которого достаточно для большинства запросов.