fcgi を使用して接続された nginx の背後で django インスタンスを実行しています (manage.py runfcgi コマンドを使用)。コードはメモリに読み込まれるため、django fcgi プロセスを強制終了して再起動しないと新しいコードをリロードできず、ライブ Web サイトが中断されます。再起動自体は非常に高速です。しかし、最初に fcgi プロセスを強制終了すると、一部のユーザーのアクションが中断されてしまい、良くありません。中断を引き起こさずに新しいコードをリロードするにはどうすればよいか疑問に思っています。アドバイスをいただければ幸いです。
5 に答える
そこで私は先に進み、Martin の提案を実装しました。これが私が思いついた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信号を適切な方法で処理します。つまり、正常にシャットダウンします。したがって、あなたがしなければならないのは、次のことだけです。
HUPシグナルをfcgiサーバーに送信します(runserverのpidfile =引数が役立ちます)
少し待ちます(flupでは子供が10秒間処理できるので、さらに2、3秒待ちます。15は適切な数値のようです)
何かがブロックした場合に備えて、KILLシグナルをfcgiサーバーに送信しました
サーバーを再起動します
それでおしまい。
FastCGI の代わりにスポーンを使用できます
私たちはついにこれに対する適切な解決策を見つけました!
http://rambleon.usebox.net/post/3279121000/how-to-gracefully-restart-django-running-fastcgi
最初に HUP シグナルを送信して再起動を知らせます。次に、Flup はすべての子に対してこれを行います。
- 非アクティブな子を停止するソケットを閉じます
- INT信号を送る
- 10秒待つ
- KILL シグナルを送信します
すべての子がなくなると、新しい子が始まります。
これは、 flup がステップ2
を実行するときに子がリクエストを処理している場合、サーバーが で停止しKeyboardInterrupt
、ユーザーに 500 エラーを与えることを除いて、ほとんど常に機能します。
解決策は、SIGINT ハンドラーをインストールすることです。詳細については、上記のページを参照してください。SIGINT を無視するだけでも、プロセスが終了するまでに 10 秒かかります。これは、ほとんどの要求に対して十分です。