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

我使用fcgi(使用manage.py runfcgi命令)在nginx连接后面运行一个django实例。 由于代码被加载到内存中,我不能重新加载新的代码,而无需重新启动django fcgi进程,从而中断实时网站。 重新启动本身是非常快的。 但是通过杀死fcgi进程,一些用户的行为会被打断,这是不好的。 我想知道如何重新加载新的代码,而不会造成任何中断。 build议将不胜感激!

我将在一个新的端口上启动一个新的fcgi进程,改变nginx配置来使用新的端口,使用nginx重新加载配置(本身是优雅的),然后最终停止旧的进程(你可以使用netstat来找出最后连接到旧端口被关闭)。

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

所以我继续执行马丁的建议。 这是我提出的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 

我遇到这个页面,同时寻找这个问题的解决方案。 一切都失败了,所以我查找了源代码:)

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

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

  2. 稍等一下(flup允许儿童进程10秒钟,所以再等一会儿; 15看起来像一个很好的数字)

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

  4. 再次启动服务器

而已。

您可以使用产卵而不是FastCGI

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

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

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

首先发送一个HUP信号来指示重启。 然后,Flup会对所有的孩子这样做:

  1. 关闭将停止不活动的孩子的插座
  2. 发送一个INT信号
  3. 等待10秒钟
  4. 发送一个KILL信号

当所有的孩子都走了,它会开始新的。

几乎所有的时间都是这样,除了如果一个孩子在flup执行第二步时处理一个请求,那么你的服务器将会被KeyboardInterrupt消失,给用户一个500错误。

解决方案是安装一个SIGINT处理程序 – 请参阅上面的页面了解详细信息。 即使只是忽略SIGINT也会让你的进程退出10秒,这对于大多数请求来说已经足够了。