1. はじめに
Flaskのデフォルトでは複数のリクエストを同時に処理することができません。HTTPリクエストを並列処理するのではなくシングル(直列)処理で行うため、同時アクセスがあると最初のリクエストの処理が完了するまで待ちが発生します。
これは公式ドキュメントにも書かれています。
While lightweight and easy to use, Flask’s built-in server is not suitable for production as it doesn’t scale well and by default serves only one request at a time. Some of the options available for properly running Flask in production are documented here.
並列処理を有効にして同時アクセスを可能にするにはthreaded=True
パラメータを設定します。
# 同時アクセスができる(並列処理が可能)
app.run(host='localhost', port=3000, threaded=True)
(注意)
WSGI(Web Server Gateway Interface)
サーバを利用している場合はこの限りではありません。例えばGunicorn
の場合、pre-fork
で複数プロセス(ワーカー)で処理を行うため、全体として並列処理が可能です。
2. ソースコード
# -*- coding: utf-8 -*-
from flask import Flask, make_response, jsonify
import time
# flask
app = Flask(__name__)
# rest api
@app.route('/hello/<string:value>', methods=['GET'])
def hello(value):
result = 'hello {0}'.format(value)
print('[start] ' + result)
time.sleep(10)
print('[end] ' + result)
return(make_response(result))
# main
if __name__ == "__main__":
# 同時アクセスができない(並列処理が不可能)
# app.run(host='localhost', port=3000)
# 同時アクセスができる(並列処理が可能)
app.run(host='localhost', port=3000, threaded=True)
3. 動作確認
Webブラウザの画面(タブ)を2つ開いてURL①、URL②にそれぞれアクセスします。並列処理が有効であればコンソールに[start]
が続くはずです。
-
画面1 : URL①
-
画面2 : URL②
C:\Temp>python sampleApp.py
* Running on http://localhost:3000/ (Press CTRL+C to quit)
[start] hello shiro
[start] hello kuro
[end] hello shiro
127.0.0.1 - - [23/Jan/2018 20:54:30] "GET /hello/shiro HTTP/1.1" 200 -
[end] hello kuro
127.0.0.1 - - [23/Jan/2018 20:54:33] "GET /hello/kuro HTTP/1.1" 200 -
threaded=True
パラメータが設定されている場合、[start]
が続けて出力されているため並列処理になっていることが分かるかと思います。
C:\Temp>python sampleApp.py
* Running on http://localhost:3000/ (Press CTRL+C to quit)
[start] hello shiro
[end] hello shiro
127.0.0.1 - - [23/Jan/2018 21:10:37] "GET /hello/shiro HTTP/1.1" 200 -
[start] hello kuro
[end] hello kuro
127.0.0.1 - - [23/Jan/2018 21:10:48] "GET /hello/kuro HTTP/1.1" 200 -
デフォルトの場合、最初にアクセスのあったURL①の[end]
が出力された後、URL②の[start]
が出力されています。つまり並列処理になっておらず、最初の処理が終わるまで待ちになっているのが分かるかと思います。
4. さいごに
今回はFlaskのデフォルトでは複数のリクエストを同時に処理することができないこと、および並列処理を有効にするにはthreaded=True
パラメータの設定が必要であることを説明しました。
実際のシステムではWSGI
サーバを利用することが多いため、この仕様/制約を気にすることは少ないと思います。Flask単体で動作させる場合には注意する必要があります。