uWSGI の設定と最適化
uWSGI は、C で実装された高機能なアプリケーションサーバーである。WSGI だけでなく、様々なプロトコルとランタイムをサポートし、エンタープライズ環境での利用に耐える豊富な機能を備えている。その反面、設定項目は膨大で、最適化には体系的な理解が必要だ。
基本設定
uWSGI はコマンドラインオプション、環境変数、設定ファイル(INI, XML, JSON, YAML)のいずれでも設定できる。実運用では INI 形式の設定ファイルが最も一般的だ。
# uwsgi.ini
[uwsgi]
# アプリケーション設定
wsgi-file = app.py
callable = application
chdir = /var/www/myapp
# ソケット設定
http = :8000
# プロセス設定
master = true
processes = 4
threads = 2
# 管理設定
vacuum = true
die-on-term = true# 設定ファイルで起動
uwsgi --ini uwsgi.inimaster = true はマスタープロセスを有効にする重要な設定だ。これにより、ワーカーの監視と再起動、graceful reload などの機能が使えるようになる。
ソケット設定
uWSGI は複数のプロトコルでリクエストを受け付けられる。
直接 HTTP リクエストを受け付ける。開発時や単体での運用に使う。
uWSGI 独自のバイナリプロトコル。Nginx との連携で使用し、HTTP より効率的。
# HTTP で直接受け付ける
http = :8000
# uwsgi プロトコル(TCP)
socket = :3031
# uwsgi プロトコル(Unix ソケット)
socket = /tmp/uwsgi.sock
chmod-socket = 666
# 複数のソケットを同時に設定可能
http = :8000
socket = /tmp/uwsgi.sock本番環境では、Nginx をリバースプロキシとして前段に置き、Unix ソケット経由で uwsgi プロトコルを使うのがベストプラクティスだ。
プロセスとスレッド
uWSGI はプロセスとスレッドを組み合わせた並行処理モデルを提供する。
# 4 プロセス × 2 スレッド = 8 並行処理
processes = 4
threads = 2
# またはワーカー数で指定(processes のエイリアス)
workers = 4
threads = 2GIL の制約により、CPU バウンドな処理ではスレッドの効果は限定的だ。しかし、I/O バウンドな処理(データベースアクセス、外部 API 呼び出し)ではスレッドが有効に機能する。
プロセス数の目安
# CPU コア数を基準に設定
# CPU バウンド: コア数
# I/O バウンド: コア数 × 2〜4
processes = 4メモリ使用量も考慮する必要がある。各プロセスはアプリケーション全体をロードするため、プロセス数 × アプリケーションのメモリ使用量がおおよその合計メモリ消費となる。
メモリ管理
長時間稼働するとメモリリークが蓄積することがある。uWSGI には、ワーカーを定期的に再起動してメモリを解放する機能がある。
# リクエスト数で再起動
max-requests = 5000
# メモリ使用量で再起動(MB 単位)
reload-on-rss = 200
# アドレス空間サイズで再起動(MB 単位)
reload-on-as = 512
# 時間で再起動(秒)
max-worker-lifetime = 3600max-requests は最も一般的な設定だ。指定した数のリクエストを処理したワーカーは、新しいワーカーに置き換えられる。これにより、メモリリークの影響を軽減できる。
# max-requests にランダム性を加える
max-requests = 5000
max-requests-delta = 500
# 4500〜5500 の範囲でランダムに再起動max-requests-delta を設定すると、すべてのワーカーが同時に再起動する「thundering herd」問題を回避できる。
バッファとタイムアウト
リクエストとレスポンスのバッファリング、タイムアウト設定は、パフォーマンスと安定性に直結する。
# リクエストボディのバッファサイズ(バイト)
buffer-size = 32768
# POST データの最大サイズ(バイト)
post-buffering = 65536
# ソケットタイムアウト(秒)
socket-timeout = 60
# HTTP タイムアウト(秒)
http-timeout = 60
# harakiri(強制終了)タイムアウト(秒)
harakiri = 60harakiri は、指定時間内にリクエスト処理が完了しない場合にワーカーを強制終了する機能だ。処理がスタックしたワーカーがリソースを占有し続けることを防ぐ。
# harakiri 設定
harakiri = 60
harakiri-verbose = trueharakiri-verbose を有効にすると、強制終了時にスタックトレースがログに出力される。デバッグに役立つ。
Lazy Apps モード
デフォルトでは、uWSGI はマスタープロセスでアプリケーションをロードし、ワーカーにフォークする。これにより、アプリケーションコードがメモリ上で共有され、メモリ効率が向上する。
しかし、一部のライブラリ(データベース接続プールなど)はフォーク後に問題を起こすことがある。その場合は lazy-apps モードを使う。
# 各ワーカーで個別にアプリケーションをロード
lazy-apps = truelazy-apps を有効にすると、各ワーカーが独立してアプリケーションをロードする。メモリ使用量は増えるが、フォーク関連の問題を回避できる。
マスターでロード後フォーク。メモリ効率が高いが、一部ライブラリで問題が発生する可能性。
各ワーカーで個別ロード。メモリ消費は増えるが、フォーク関連の問題を回避。データベース接続プールとの相性が良い。
Nginx との連携
本番環境での一般的な構成は、Nginx + uWSGI だ。
# uwsgi.ini
[uwsgi]
socket = /tmp/uwsgi.sock
chmod-socket = 666
wsgi-file = app.py
callable = application
processes = 4
threads = 2
master = true
vacuum = trueNginx の設定例:
# /etc/nginx/sites-available/myapp
upstream uwsgi_backend {
server unix:///tmp/uwsgi.sock;
}
server {
listen 80;
server_name example.com;
location / {
include uwsgi_params;
uwsgi_pass uwsgi_backend;
}
location /static {
alias /var/www/myapp/static;
}
}uwsgi_params は uWSGI に必要な環境変数を設定するファイルで、Nginx に付属している。
Emperor モード
複数のアプリケーションを一元管理する場合、Emperor モードが便利だ。
# Emperor を起動(/etc/uwsgi/vassals ディレクトリ内の設定ファイルを監視)
uwsgi --emperor /etc/uwsgi/vassals各アプリケーションの設定ファイル(vassal)を /etc/uwsgi/vassals に配置すると、Emperor が自動的に起動・監視する。設定ファイルを更新すると、対応するアプリケーションが自動で再起動される。
# /etc/uwsgi/vassals/app1.ini
[uwsgi]
socket = /tmp/app1.sock
wsgi-file = /var/www/app1/app.py
callable = application
processes = 2# /etc/uwsgi/vassals/app2.ini
[uwsgi]
socket = /tmp/app2.sock
wsgi-file = /var/www/app2/app.py
callable = application
processes = 4統計情報とモニタリング
uWSGI は組み込みの統計サーバーを提供している。
# 統計ソケットを有効化
stats = /tmp/uwsgi-stats.sock
# または HTTP で公開
stats = :9191
stats-http = true# 統計情報を取得
uwsgitop /tmp/uwsgi-stats.sock
# または curl で
curl http://localhost:9191統計情報には、各ワーカーのステータス、リクエスト数、メモリ使用量などが含まれる。Prometheus や Grafana と連携して可視化することも可能だ。
推奨設定テンプレート
本番環境向けの設定テンプレートを示す。
# uwsgi.ini(本番環境テンプレート)
[uwsgi]
# アプリケーション
wsgi-file = app.py
callable = application
chdir = /var/www/myapp
# ソケット
socket = /tmp/uwsgi.sock
chmod-socket = 666
# プロセス管理
master = true
processes = 4
threads = 2
enable-threads = true
# メモリ管理
max-requests = 5000
max-requests-delta = 500
reload-on-rss = 200
# タイムアウト
harakiri = 60
harakiri-verbose = true
socket-timeout = 60
# ログ
logto = /var/log/uwsgi/app.log
log-date = true
# クリーンアップ
vacuum = true
die-on-term = true
# 統計
stats = /tmp/uwsgi-stats.sockuWSGI の設定項目は膨大だが、基本的な設定から始めて、負荷テストとモニタリングの結果を見ながら段階的に最適化していくのが現実的なアプローチだ。











