1. Gunicornとは
Gunicornは、Unix系OS上で動作する高性能なPython WSGI HTTPサーバーです。HTTPリクエストを解釈するゲートウェイサービスとして機能します。通常、NginxのようなリバースプロキシやAWS ELBのようなロードバランサと、DjangoやFlaskなどのWebアプリケーションの間に配置されます。その動作モデルはプリフォークワーカーモデルに基づいており、eventletやgreenletをサポートしています。
2. Gunicornの特徴
- ほとんどのPython Webフレームワークと互換性があります。
- 簡単に導入できます。
- 軽量なリソース消費です。
- 現在のところ、Linux環境でのみ動作し、Windowsプラットフォームはサポートしていません。
3. WSGI HTTPサーバーについて
WSGI(Web Server Gateway Interface)は、WebサーバーでもWebアプリでもありません。WebサーバーとWebアプリ(またはWebアプリケーションフレームワーク)を分離し、再び接続するための橋渡し役です。これは、Webサーバー(例:Apache、Nginx)とWebアプリ(またはWebアプリケーションフレームワーク)間の標準を定義する汎用的なインターフェース仕様です。この仕様により、Webアプリ開発者は、HTTPリクエストの受信、接続の確立、レスポンスの返却といった煩雑なネットワーク層の実装を気にせず、ビジネスロジックやHTMLドキュメントの生成に集中できます。また、異なるWebサーバーとWebアプリ/フレームワークを簡単に組み合わせることができます。
4. プリフォークワーカーモデルについて
ワーカーモデルは、マスタープロセスが一連のワーカープロセスを管理するモデルです。
forkは、ワーカープロセスがマスタープロセスからフォーク(複製)されることを意味します。
pre-は、いかなるクライアントリクエストが到着する前に、マスタープロセスから複数のワーカープロセスがフォークされ、リクエストを待機している状態を指します。
実行フロー:ワーカープロセスが作成されると、Python Webアプリケーションがインスタンス化されます。そして、ワーカープロセスはポートをリッスンし、リクエストを処理します。リクエストが到着すると、ワーカープロセスはHTTPリクエストを解析し、Python Webアプリケーションを呼び出して処理結果を得た後、HTTPレスポンスとして整形し、TCPを介してクライアントに返します。
注:マスタープロセスはリクエストを処理するのではなく、ワーカープロセスの作成、破棄、および負荷に応じた増減を管理するだけです。(起動時に設定した--workersパラメータはワーカーの数ですが、gunicornはマスタープロセスも作成します。そのため、workersを1に設定しても、アプリは少なくとも2つのプロセス(マスターが管理、ワーカーがリクエストを処理)になります)。
Gunicornにとって、gunicornはWSGIの実装ですが、同時にWebサーバーも内蔵しており、直接Webサービスを提供できます。FlaskやDjangoのようなほとんどのWebアプリケーションフレームワークもWebサーバーを内蔵しています。しかし、本番環境では、通常、役割分担が明確で、WebフレームワークのFlaskやDjangoはアプリケーション開発にのみ使用され、GunicornはPython Webアプリケーションの実行と管理にのみ使用され、その前にNginxのような専用のWebサーバーが配置されます。
5. Gunicornの使用方法
Gunicornは、異なるワーカープロセスタイプを使用することをサポートしており、worker-classパラメータで設定できます。起動後、gunicornのすべてのワーカーは一組のリスナー(Gunicornは複数のソケットをバインドできるため、一組と表現)を共有します。ワーカーが起動すると、各リスナーに対してWSGIサーバーが作成され、HTTPリクエストをリッスンし、appオブジェクトを呼び出してリクエストを処理します。
Gunicornの動作モードは主に同期ワーカー使用と非同期ワーカー使用に分かれます。
5.1. 同期ワーカー(Sync Worker)
デフォルトで最もシンプルなワーカーモードが同期モードです。各ワーカープロセスは一度に一つのリクエストしか処理できません。この時点で、他のリクエストがこのワーカープロセスに割り当てられた場合、ブロックされ、最初のリクエストが完了するのを待たなければなりません。また、リクエストごとにプロセスが生成されるため、同時実行時にはCPUとメモリを大量に消費します。
注:したがって、アクセス量が少なく、I/OではなくCPU集約型のシナリオにのみ適しています。しかし、利点もあります。一つのワーカープロセスがクラッシュしても、一つのリクエストにのみ影響を与え、他のリクエストには影響しません。
5.2. 非同期ワーカー(Async Worker)
非同期ワーカーにはGeventとEventletの2種類があり、どちらもGreenletをベースに実装されています。非同期ワーカーを使用すると、複数のリクエストを同時に処理でき、同期ワーカーのように一つのリクエストで後続のリクエストがすべてブロックされることはありません。
注:gunicornは、対応するワーカークラスを設定することで、これらの非同期Pythonライブラリを使用できます。例えば、単一のコアマシンでgeventを実行したい場合:
gunicorn --worker-class=gevent --worker-connections=1000 --workers=3 my_app:app
解説:worker-connectionはgeventワーカークラスの特殊な設定です。(2*CPU数)+1が依然として推奨されるワーカー数です。ここでは単一コアなので、3つのワーカーを設定しています。この場合、最大の同時リクエスト数は3000(3つのワーカー * 1000の接続数/ワーカー)です。
6. Gunicornはどのように高並行を実現するか?
Gunicornにとって、起動時にすでにワーカープロセスが事前にフォークされています。複数のリクエストが到着すると、これらのワーカープロセスを順番に再利用することで、サーバーの同時処理能力を向上させることができます。
ワーカー数の設定は、一般的に2*CPU数+1が推奨されます。こうすることで、いかなる時も、約半分のワーカーがI/O処理に、残りの半分がCPU処理に費やされることになります。もしマルチプロセスとマルチスレッドを同時に開始する場合(つまりgthreadタイプのワーカーを選択する場合)、総同時実行数(ワーカープロセス数×スレッド数)の設定も依然として2*CPU数+1が推奨されます。
7. Gunicornのデプロイ
GunicornはWSGI HTTPサーバーです。
7.1. Gunicornのインストール
【ここではCentOS7システムを例にします】
- まず、仮想環境を作成します。
cd /opt/my_project mkdir venv python3 -m venv venv - 仮想環境をアクティブにします。
source venv/bin/activate - requirements.txtファイルに基づいて依存パッケージをインストールします。
pip install -r requirements.txt - Gunicornをインストールします。pipで直接インストールできます。
pip install gunicorn
7.2. 基本的な設定ファイルの作成
プロジェクトのルートディレクトリに`gunicorn_config.py`のような設定ファイルを作成します。以下は、Djangoアプリケーションを例とした詳細な設定ファイルの例です。
# gunicorn_config.py
import multiprocessing
import logging
from logging.handlers import RotatingFileHandler
# バインド先のアドレスとポート
bind = '127.0.0.1:8000'
# ワーカープロセスの数 (CPUコア数の2倍+1が推奨)
num_workers = multiprocessing.cpu_count() * 2 + 1
# ワーカークラスの設定 (gevent, eventlet, syncなど)
worker_class = 'gevent'
# 各ワーカーが処理できる最大接続数
worker_connections = 1000
# リクエストのタイムアウト時間(秒)
timeout = 30
# アクセスログとエラーログの設定
accesslog = './logs/gunicorn_access.log'
errorlog = './logs/gunicorn_error.log'
# ログのローテーション設定
log_level = 'info'
access_log_format = '%(h)s - %(r)s - %(s)s - %(b)s bytes - %(L)s'
# デーモンモードで実行するかどうか
daemon = False
7.3. Gunicornの起動
上記の設定ファイルを使用してGunicornを起動します。`my_app:app`は、アプリケーションオブジェクトが定義されているモジュールと変数名を指します。
gunicorn --config gunicorn_config.py my_app:app
7.4. 本番環境での設定例
本番環境では、プロセスの起動・停止や状態監視にはSupervisorなどのツールを使用し、Gunicornの前にNginxのようなリバースプロキシを配置することが一般的です。
Supervisor設定例 (supervisor_gunicorn.conf)
[program:gunicorn_app]
process_name=%(program_name)s
directory=/opt/my_project
command=/opt/my_project/venv/bin/gunicorn --config /opt/my_project/gunicorn_config.py my_app:app
autostart=true
autorestart=true
user=www-data
redirect_stderr=true
stdout_logfile=/var/log/gunicorn/app.log
Nginx設定例 (nginx.conf)
server {
listen 80;
server_name example.com;
location / {
proxy_pass http://127.0.0.1:8000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
8. Gunicornのコマンドラインパラメータ
--config CONFIG, -c CONFIG
設定ファイル(Pythonファイル)を指定します。
--bind ADDRESS, -b ADDRESS
指定したソケットにバインドします。
--daemon, -D
Gunicornプロセスをデーモンモードで実行します。
--workers INT, -w INT
ワーカープロセスの数を指定します。
--worker-class NAME, -k NAME
ワーカークラスを指定します(sync, eventlet, gevent, tornado, gthread, gaiohttpなど)。
--backlog INT
最大保留接続数を設定します。
--log-level LEVEL
ログ出力レベルを設定します。
--access-logfile FILE
アクセスログの出力先ファイルを指定します。
--error-logfile FILE
エラーログの出力先ファイルを指定します。