如何优雅地重启django在nginx后面运行fcgi?

时间:2008-12-12 03:59:33

标签: django nginx deployment fastcgi

我正在使用fcgi(通过使用manage.py runfcgi命令)连接nginx后面的django实例。由于代码被加载到内存中,因此无法在不杀死并重新启动django fcgi进程的情况下重新加载新代码,从而中断了实时网站。重启本身非常快。但是通过首先杀死fcgi进程,一些用户的操作将被中断,这是不好的。 我想知道如何在不造成任何中断的情况下重新加载新代码。建议将受到高度赞赏!

5 个答案:

答案 0 :(得分:15)

所以我继续执行马丁的建议。这是我提出的bash脚本。

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

答案 1 :(得分:15)

我会在新端口上启动一个新的fcgi进程,更改nginx配置以使用新端口,具有nginx重新加载配置(这本身就是优雅的),然后最终停止旧进程(可以使用netstat查找何时关闭旧端口的最后一次连接。)

或者,您可以更改fcgi实现以分叉一个新进程,关闭子进程中除fcgi服务器套接字之外的所有套接字,关闭父进程中的fcgi服务器套接字,在子进程中执行一个新的django进程(使其使用fcgi服务器套接字),并在关闭所有fcgi连接后终止父进程。 IOW,为runfcgi实现正常重启。

答案 2 :(得分:10)

我在寻找此问题的解决方案时遇到了此页面。其他一切都失败了,所以我查看了源代码:)

解决方案似乎更简单。 Django fcgi服务器使用flup,它以正确的方式处理HUP信号:它正常关闭。所以你要做的就是:

  1. 将HUP信号发送到fcgi服务器(runserver的pidfile =参数将派上用场)

  2. 等一下(痘痘允许孩子进行10秒钟,所以再等几下; 15看起来像个好人数)

  3. 将KILL信号发送到fcgi服务器,以防万一被阻止

  4. 再次启动服务器

  5. 就是这样。

答案 3 :(得分:3)

您可以使用产卵代替FastCGI

http://www.eflorenzano.com/blog/post/spawning-django/

答案 4 :(得分:2)

我们终于找到了合适的解决方案!

http://rambleon.usebox.net/post/3279121000/how-to-gracefully-restart-django-running-fastcgi

首先发送一个HUP信号以发出重启信号。 Flup将对其所有孩子这样做:

  1. 关闭将停止非活动儿童的套接字
  2. 发送INT信号
  3. 等待10秒
  4. 发送KILL信号
  5. 当所有的孩子都离开后,它会开始新的。

    这几乎在所有时间都有效,除非如果孩子在flup执行步骤2时正在处理请求,那么您的服务器将会死于KeyboardInterrupt,从而给用户带来500错误。

    解决方案是安装SIGINT处理程序 - 有关详细信息,请参阅上面的页面。即使只是忽略SIGINT,您的进程也会在10秒内退出,这足以满足大多数请求。

豫ICP备18024241号-1