Я запускаю экземпляр 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 секунд для выхода, которого достаточно для большинства запросов.