1. まとめトップ

Python WSGI サーバ(マルチプロセス) for Windows

WindowsでマルチプロセスのWSGIサーバを立ち上げるにはどうすべきなのか考えてみました。

更新日: 2018年04月26日

0 お気に入り 2845 view
お気に入り追加

この記事は私がまとめました

はじめに

Windowsではpreforkが使えないことからLinux由来のソフトではマルチプロセス動作できません。Pythonでは基本機能でマルチプロセスの機能があることから、もしかするとできるかもしれないという考えから挑戦してみました。

Python WSGIサーバ for Windows

1.Gunicorn
2.Apache + mod_wsgi
3.gevent
4.tornado
5.twist
6.Python標準
7.wfastcgi

いろいろありますが、Python基本機能のマルチプロセスを使用するためには、Pythonそのもので通信制御するタイプの実装でなければいけません。

結果としてgeventを用いることにしました。

PythonのAPサーバを複数プロセス立ち上げる

同じポート番号は使えないため、それぞれのプロセスで異なるポートを立ち上げる必要があります。

multiprocessing は、 threading と似た API で複数のプロセスを生成をサポートするパッケージです。

WSGIServer(('', 8000), application).serve_forever()

geventでWSGIServerを起動するにはこの命令です。

import multiprocessing
from gevent.wsgi import WSGIServer

wsgi_server_backup = []

def application(environ, start_response):
....status = '200 OK'

....任意処理

....headers = [
........('Content-Type', 'text/html')
....]

....start_response(status, headers)
....return [body]

def gevent_start(p_port):
...._server = WSGIServer(('', 8000 + p_port), application)
...._server.serve_forever()

if __name__ == '__main__':
....for _i in range(4): #立ち上げる数の調整
........p = Process(target=gevent_start, args=(_i,))
........wsgi_server_backup.append(p)
........p.start()
....for _server in wsgi_server_backup:
........_server.join()

大体こんな感じで動きます。
インデントは適宜調整してください。

Nginxでロードバランスする

http {
....upstream myapp1 {
........server srv1.example.com;
........server srv2.example.com;
........server srv3.example.com;
....}

....server {
........listen 80;

........location / {
............proxy_pass http://myapp1;
........}
....}
}

この記述が基本になります。

http {
....upstream myapp1 {
........server localhost:8000;
........server localhost:8001;
........server localhost:8002;
....}

....server {
........listen 80;

........location /WSGI {
............proxy_pass http://myapp1;
........}
....}
}

こんな感じで良いでしょう。

以下も重要です。
ajaxでrestなどをやっているとうまく動かないことが出てきます。

server {
....listen 80;
....server_name hoge.example.com;
....location / {
........add_header Access-Control-Allow-Origin *;
........add_header Access-Control-Allow-Methods "POST, GET, OPTIONS";
........add_header Access-Control-Allow-Headers "Origin, Authorization, Accept";
........add_header Access-Control-Allow-Credentials true;
........proxy_pass http://localhost:8888;
....}
}

結果

マルチプロセスで動作すると同時にロードバランスも問題なく動作するようです。
ただlinuxのように内部ポート無いのでソケットを大量に使ってしまいます。
それだけが心配ですね。

(2016/6/29追記)
これにプラスして死んでしまったプロセスを死活チェックして、死んだプロセスを停止させて
再度起動する処理を組みこみしてみました。
nginxのロードバランスの設定でチェックタイミングを設定とあわせて実施すると
これはこれで行けそうな気がします。しばらく試行してみます。
動作が軽いのが良いですね。

(2017/3/16)
nginxのロードバランスを使ったのですが、接続先へ復活したかどうかのリトライが正式アクセスになってしまうので、裏でやってくれる仕様ではないのが残念。Plusでないとダメのようです。
Windowsのみではこの部分が難しいです。
HAProxyみたいなのがあればよいんですけどね。今のところはこれを間に挟むのがよさそうです。VirtualBoxなどで作るしかないか。

(2018/4/26)
結果としてこれは失敗でした。HAProxyでも通信しないと死活がわからないので結局ロストしてしまうことがあります。やっぱり1ポートでうけて、自前でプロセス管理とかしないとダメっぽいですね。そうなってくるとwfastcgiでいいじゃんと思う自分がそこにいました。

1