274


Python 3.3.5 + Flaskでサーバアプリを作っています。

## 内容

FlaskにHTTPリクエストを送ると即座にレスポンスを返してくれますが、

  * 2つ以上のリクエストを同時に送る

もしくは

  * 早かった方のリクエストの処理中に続けてリクエストを送る

といった事をすると、遅かった方のリクエストのレスポンスは早かった方へのレスポンスが完了するまで待たされます。

単一スレッドで処理しているだからだと思われますが、これをFlaskで並列処理できる方法はありませんでしょうか。

## テストに使ったコード

[code]

    if __name__ == '__main__':
        app = Flask(__name__)
        app.config.update(PROPAGATE_EXCEPTIONS = True)
    
        @app.route('/')
        def greet():
            n = randrange(1, 10)
            sleep(n)
            return 'Hello world! I slept {0}[s].'.format(str(n))
    
        app.run()
    
[/code]

これは、リクエストが飛んできたら乱数を元に1 - 10秒待ち何秒待ったか返すコードです。

ブラウザのタブを2つ用意し、両方素早くlocalhost:5000へアクセスすると、先にアクセスした方にレスポンスが返ってきてから後の方の待つフェーズが始まることが待ち時間からわかります。

もしFlaskが並列でレスポンスを返すことができたら、待ち時間の乱数が小さかったほうが先に返ってくるはずです。


CC BY-SA 3.0
2014-12-02T18:26:57.763
272
2014-12-16T04:33:44.997
197
question
python flask
Flaskにおける複数リクエストの並列処理


flask.Flask.runのオプションにprocessesまたはthreadedを指定する事で可能だと思います。
windows環境ではforkがないためproessesはエラーとなりました。

[code]

        app.run(processes=3)
    
[/code]

または

[code]

        app.run(threaded=true)
    
[/code]

別のブラウザから同時アクセスして同時に処理されることを確認しました。

runのオプションはwerkzeugに渡されるそうなのでoptionsに関してはWerkzeugのドキュメントを参照する必要があります。

>   * options – the options to be forwarded to the underlying Werkzeug server.
> See werkzeug.run_simple() for more information.
>

[Flask.run
(bitbucket.org)](http://a2c.bitbucket.org/flask/api.html?highlight=flask#flask.Flask.run)  
[werkzeug parameters (pocoo.org)](http://werkzeug.pocoo.org/docs/0.9/serving/)


CC BY-SA 3.0
2014-12-02T23:22:48.073
274
2014-12-02T23:29:33.670
2014-12-02T23:29:33.670
728
728
272
answer


gunicornやwaitress, cherrypyなどのwsgiサーバーを使えばよいでしょう。
とりあえずflaskのサイトにはcherrypyで実行する例がありました。

<http://flask.pocoo.org/snippets/24/>


CC BY-SA 3.0
2014-12-12T08:58:39.607
1542
2014-12-12T08:58:39.607
2167
272
answer


asyncioを使うことでI/Oを多重化する方法があります。

Python3.3上でasyncioを使ったflaskアプリを作成するには、次のことが必要です。

  1. asyncioをインストールする

asyncioは、Python 3.4では標準ライブラリの一つですが、 Python 3.3では、asyncioを別途インストールすることで使用できます。

<https://pypi.python.org/pypi/asyncio>

  2. asyncioに対応したflaskを使う

asyncioを使うように手を入れたflaskがいくつか公開されているようです。 例えば、以下のものが見つかりました。

<https://pypi.python.org/pypi/Flask-Async/0.11-dev-20140215>

gunicornなどのような、preforkを行うwsgiサーバと組み合わせることも可能です。

なお、テストコードにあるようなsleep文は、

[code]

    yield from asyncio.sleep(n)
    
[/code]

に書き換えます。


CC BY-SA 3.0
2014-12-16T01:55:59.180
1626
2014-12-16T04:33:44.997
2014-12-16T04:33:44.997
2430
2430
272
answer


Flask.run() は開発用サーバーであり、実際にサービスを提供するために利用するためのものではありません。 一般的な構成には、

  * 静的ファイル配信を nginx で行い、 nginx からリバースプロキシして gunicorn か uWSGI で Flask アプリを動かす。
  * Apache と mod_wsgi を使う。

といった選択肢があります。個人的には前者がお勧めです。


CC BY-SA 3.0
2014-12-16T03:39:05.863
1653
2014-12-16T03:39:05.863
3019
272
answer