カカドゥ開発者ブログ

株式会社カカドゥのエンジニアブログです。Python, Django, SEO成分が多めです。

gunicornでgraceful restart(reload application)する方法

こんにちはカカドゥの増田です。

現在開発しているサービスは、Python + Django + Gunicornで開発しています。

これまでの経験では、Apache httpdにmod_perlやmod_phpで動かす運用をしていたため、業務レベルのサービスをスタンドアロンなアプリケーションサーバ単体で動かすのは実は初めてだったりします。

そこで、Gunicornでは、デプロイするときにApacheで言うところのgraceful restartをどうやったらできるのかなと思って調べたところ、

kill -HUP masterpid

してやればいいということが分かりました。日本語で説明している資料がなかったので記録している次第です。

公式ドキュメントには、以下のように説明されています。

How do I reload my application in Gunicorn?

You can gracefully reload by sending HUP signal to gunicorn:

$ kill -HUP masterpid

FAQ — Gunicorn 19.3.0 documentation

動作の仕組みとしては、gunicorn/arbiter.py at e0287108720b19ac520485349091df07d5c2a7d2 · benoitc/gunicorn · GitHubでコードを読むことができますが、マスタープロセスがHUPシグナルを受け取ると、新しくworkerを生成して、古いworkerをgracefully shutdownするとあります。

def handle_hup(self):
        """\
        HUP handling.
        - Reload configuration
        - Start the new worker processes with a new configuration
        - Gracefully shutdown the old worker processes
        """
        self.log.info("Hang up: %s", self.master_name)
        self.reload()

実際、kill -HUPをやってみるとworkerのpidが変わったことが確認できました。(もちろん、アプリケーションの動作が最新に切り替わったことも確認)

(env)root@host:~# pgrep gunicorn
14799  <-- master
14949  <-- worker
(env)root@host:~# kill -HUP 14799
(env)root@host:~# pgrep gunicorn
14799  <-- master
15012  <-- worker

これでサービスを落とすことなくデプロイする運用が見えました。一安心ですね。