PythonでWebアプリケーションを作成した後サーバー上で稼働させる場合、アプリケーションサーバが必要となります。(開発時は組み込みのサーバーで十分ですが、本番で使用することは推奨されていません。)ここではPythonでよく使われるuWSGIというアプリケーションサーバについて学習しましょう。
Contents
uWSGIとは
WSGIとは
uWSGIについて学習する前に、WSGIについて学習しましょう。WSGI(Web Server Gateway Interface) とは、PythonのWebアプリケーションとWebサーバー間とのやり取りの規約、プロトコールのことでPEP333で定義されています。
https://www.python.org/dev/peps/pep-3333/
Pythonの大抵のWebフレームワークはこのWSGIという規約に則っています。有名どころとして以下のフレームワークが挙げられます。
- Django
- Flask
- Bottle
uWSGIとは
uWSGIとはPythonでWebサービスを動かすためのアプリケーションサーバ(以降、APサーバーと略することがあります。)の一種です。上記のWSGIに則ったアプリケーションを動作させるアプリケーションサーバをWSGIアプリケーションコンテナやWSGIサーバなどと呼びます。uWSGIは、このWSGIアプリケーションコンテナの一種です。つまり、WSGIに準拠したアプリケーションであれば、上で挙げたDjangoやFlask以外でも動かすことが可能です。補足ですが、WSGIサーバーにはuWSGI以外にGunicornというものもあります。
Webサーバとの連携
uWSGIは動作させたアプリケーションとWebサーバーと以下の方法で通信させることができます。
- UNIXドメインソケット
- HTTP
UNIXドメインソケットは高速でAPサーバーとWebサーバー間の通信を行うことが可能です。ただし、直接リクエストしたりレスポンスを参照することができないため、トラブルが起きた際には調査が難航するかもしれません。
HTTPはソケット通信より速度面で劣りますが、最近のサーバーは低価格なものでもそこそこ性能がありますので内部の通信でHTTPを使用してもそれほど問題にならないと思います。

また、静的ファイルがないAPIの場合はWebサーバーを経由せずに、直接クライアントと通信するのも一つの手でしょう。

uWSGIのインストール
Pythonがインストールされている環境であれば、pipでインストール可能です。
pip install uWSGI
uWSGIでFlaskを動かしてみる
それでは、ここから実際にWSGIに準拠したFlaskをuWSGIで動かしてみましょう。Flaskについては以下も合わせて参考にしてみてください。
サンプルアプリケーションを作成する
あらかじめFlaskとuWSGIをインストールしておきましょう。
pip install uWSGI pip install flask
次にFlaskの簡単なアプリケーションを作成します。run.pyという名前で以下のプログラムを作成しましょう。
# run.py from flask import Flask, jsonify app = Flask(__name__) @app.route('/') def api_sample(): """ APIサンプル :return: """ result = {"code": "001", "name": "apple"} return jsonify(ResultSet=result) if __name__ == '__main__': app.run()
/にアクセスすると、jsonを返すだけのプログラムです。python run.py
とコマンドを実行するとデバッグ用のサーバーが起動しますので、"http://127.0.0.1:5000/"にアクセスしてください。jsonが返されればOKです。確認が終わればCtrl+c(Windows系の方はctrl+z)でサーバーを中断してください。
uWSGIコマンドで実行
次にuWSGIコマンドで実行してみましょう。以下のコマンドを実行してください。
uwsgi --http=0.0.0.0:8080 --wsgi-file=run.py --callable=app
ブラウザやcurlコマンドでhttp://127.0.0.1:8080にアクセスしてください。先程のjsonが出力されればuWSGI経由での実行は成功です。
uWSGIコマンドではオプションにサーバーの設定を指定します。httpオプションはアクセスを許可するホストとポートを、wsgi-fileオプションではwsgiで動作するファイルを指定します。
設定ファイルから実行する
さて、実運用でサーバーを動かす場合、上記で指定したアクセス許可ホスト、ポート番号以外にも、プロセス数、スレッド数、実効ユーザー、実効グループ、リロード方式、ソケット出力先、権限、ログ出力形式、出力先、etc...などなど様々な項目を設定する必要があります。
全てコマンドのオプションで指定することができるのですが、オプションが長すぎて取り回しが悪いですね。このため、大抵のサービス系コマンドと同様、uWSGIコマンドはオプションをひとまとめに記述できる設定ファイルを指定することができます。
設定ファイルで試してみましょう。uwsgi.iniというini形式のファイルを作成します。セクション名は[uwsgi]を指定します。
# uwsgi.ini [uwsgi] # wsgiファイル wsgi-file=run.py callable=app # アクセス許可ホスト:ポート http=0.0.0.0:8080
設定ファイルが完成したら、以下のコマンドで実行してみましょう。
uwsgi uwsgi.ini
先程と同様、http://127.0.0.1:8080 にアクセスして出力を確認してみてください。
uWSGIの設定項目
次に、実際にサーバーとして動かす場合の設定値を紹介します。いずれもCentos等のUnix系サーバで動かすことを想定しています。
デーモン化
先程実行した際、コマンドライン上にログが出力され、コマンドラインを終了するとサービスも停止してしまいましたが、以下のオプションでデーモン化することが可能です。
daemonize = /var/log/uwsgi.log log-reopen = true log-maxsize = 8000000 logfile-chown = on logfile-chmod = 644
log-reopenリロード後にログをリオープンします。log-maxsizeはログの最大サイズでそれを超過するとローテートされますが、Linuxのログローテートを使用してもよいでしょう。
また、以下のように日付をファイル名に指定することもできます。
daemonize = /var/log/uWSGI-@(exec://date +%%Y-%%m-%%d).log
ディレクトリ
上のサンプルではカレントディレクトリで実行しましたが、chdirでWSGIアプリケーションを配置したディレクトリを設定で指定することができます。
例えば、/opt/apps/current/sample_apiというディレクトリにアプリケーションを配置した場合、以下のように記述することができます。
current_release = /opt/apps/current/sample_api chdir = %(current_release) wsgi-file=%(current_release)/run.py
上のcurrent_releaseは変数となっており、%(current_release)で他の項目で使い回すことができます。
実効ユーザー・グループ
実効ユーザー、グループはuid、gidで指定することができます。
uid = uwsgi_user gid = uwsgi_group
プロセス、スレッド
processes、threadsでプロセス数、スレッド数を指定することができます。thunder-lockでリクエストを受けるプロセスを分散することができます。max-requestsで指定した回数リクエストを受けるとリロードします。また、一斉にリロードするとその間サービスが止まりますので、max-requests-deltaでリロードのタイミングにプロセスごとに差を設けます。
processes = 4 threads = 2 thunder-lock = true max-requests = 3000 max-requests-delta = 300 master = True
uWSGIの停止、再起動、リロード
デーモン化したuwsgiを停止、リロードするにはpidファイルが必要です。設定に以下を追記します。
# pidファイルの位置を指定 pidfile = /var/run/uwsgi/uwsgi.pid # 前回異常終了した場合、起動時にpidファイルをクリア vacuum = true
停止
uwsgi --stop /var/run/uwsgi/uwsgi.pid
リロード
uwsgi --reload /var/run/uwsgi/uwsgi.pid
また、プロセスIDがわかっていればシグナルでも操作可能です。SIGHUPの場合、reloadと同じ動作となります。
kill -HUP `cat /var/run/uwsgi/uwsgi.pid`
今回はuWSGIについて概要を説明しました。次回はLinuxサーバー上でuWSGIをセットアップする方法について説明する予定です。