🙆

gunicorn syncワーカーの全体像メモ

2022/02/21に公開

gunicornとは?

Gunicornは、PythonのWeb Server Gateway Interface(WSGI)を実装するHTTPサーバーである
https://ja.wikipedia.org/wiki/Gunicorn

対象読者

・gunicorn syncワーカーをざっくり把握したい人
・APサーバーが好きな人

はじめに

先日、全く知見がなかったgunicorn周りの不具合調査をする機会がありました。
その際に、gunicornの包括的な内容の日本語記事が見当たらず理解に苦労したので、個人的に重要だった点を書き留めておきます。

この記事で書かないこと

・gunicornの具体的な使い方
・syncワーカーって何って話

前提

  • gunicorn: 20.0.4
  • ワーカータイプ: syncタイプ

でのお話

基本設計

gunicornのsyncワーカータイプでは、マルチプロセス - preforkモデルを採用している。

つまり、masterプロセス(親プロセス)が、ワーカー(子プロセス)をフォークし、ワーカーが直に1リクエストづつ処理する。

root@2bb4dr5e9dae:/usr/src/app# gunicorn wsgi:application -w 3 --bind 0.0.0.0:8000
root@2bb4dr5e9dae:/usr/src/app# ps auxf
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.0   5492  3200 pts/0    Ss+  18:30   0:00 gunicorn wsgi:application -w 3 -t 100 --bind 0.0.0.0:8000
root       109  0.0  0.0  28992 22912 pts/0    S+   18:30   0:03 /usr/local/bin/python /usr/local/bin/gunicorn wsgi:application -w 3 -t 100 --bind 0.0.0.0:8000
root      9953  2.7  0.7 1146564 176672 pts/0  Sl+  19:17   0:27  \_ /usr/local/bin/python /usr/local/bin/gunicorn wsgi:application -w 3 -t 100 --bind 0.0.0.0:8000
root      9954  2.8  0.7 1146568 176676 pts/0  Sl+  19:17   0:29  \_ /usr/local/bin/python /usr/local/bin/gunicorn wsgi:application -w 3 -t 100 --bind 0.0.0.0:8000

また、preforkなので、ワーカーはサーバー起動直後に全て作成されselect状態となる。
起動後は特に操作しない限りワーカーは増えたり/減ったりしない。

プロセス/ワーカーの操作

masterプロセスにシグナルを送ることでワーカーの操作ができる。

ex, TTINでワーカーを+1増やす

root@2bb4dr5e9dae:/usr/src/app# kill -TTIN 109
root@2bb4dr5e9dae:/usr/src/app# pgrep gunicorn
109
9953
10263
10264

ワーカーをkillすると、masterプロセスが検知してワーカーを作成し直す

root@2bb4dr5e9dae:/usr/src/app# kill -9 9954
root@2bb4dr5e9dae:/usr/src/app# pgrep gunicorn
109
9953
10263

詳細

起動オプション

チューニング等で使った起動オプション

  • --max-requests INT

ワーカーごとに、リクエストをN数捌いたら、ワーカー(子プロセス)を再起動させるオプション。
再起動することでメモリが解放されるため、--max_requests_jitterとセットで、緩めのメモリリーク対策などにも使える。

  • --timeout INT

ワーカーが捌くリクエストごとのタイムアウト設定。あまりに長いとワーカーが枯渇してリクエスト詰まったりするので注意

実装としては、timeoutするとワーカーにSIGABRTシグナルが送られるよう。参考

  • --backlog INT

(ワーカーが不足しリクエストが詰まった場合などで)、待機させられるリクエストの数。

ちなみに、実際に待機中のリクエスト数を取得/監視する方法はgunicornとしては用意していないようだった。参考

  • --reload INT

アプリケーションのソースコードの変更を監視して、ワーカーをダウンタイムなく再起動(入れ替え)する。詳細
ローカル開発で使用したりします

graceful restartする方法

ダウンタイムなしでrestartかけたい場合は、masterプロセスに対し、HUPシグナルを送ればよい。
masterプロセスが、新しいワーカーを立ち上げ、古いワーカーをgracefulにシャットダウンしていく。
https://docs.gunicorn.org/en/stable/faq.html#how-do-i-reload-my-application-in-gunicorn

root@2bb4dr5e9dae:/usr/src/app# kill -HUP 117

参考

https://docs.gunicorn.org/en/stable
https://blog.yuuk.io/entry/2015-webserver-architecture?amp=1

Discussion