25

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

4

5 回答 5

16

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

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

于 2008-12-12T07:44:37.283 回答
16

所以我继续执行了马丁的建议。这是我想出的 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
于 2009-06-05T17:16:19.377 回答
10

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

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

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

  2. 稍等(flup 允许孩子处理 10 秒,所以再等几秒;15 看起来不错)

  3. 将 KILL 信号发送到 fcgi 服务器,以防万一有什么东西阻止了它

  4. 再次启动服务器

就是这样。

于 2009-07-21T21:59:37.283 回答
3

您可以使用生成而不是 FastCGI

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

于 2009-01-17T10:15:26.403 回答
2

我们终于找到了正确的解决方案!

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

首先向flup发送一个HUP信号来表示重启。然后 Flup 将对它的所有子节点执行此操作:

  1. 关闭将停止非活动孩子的套接字
  2. 发送一个 INT 信号
  3. 等待 10 秒
  4. 发送 KILL 信号

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

这几乎在所有时间都有效,除了如果在flup执行 step 时孩子正在处理请求,2那么您的服务器将死机KeyboardInterrupt,给用户一个 500 错误。

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

于 2011-02-14T10:55:29.750 回答