flask+gunicornでgeventを使い、非同期処理にする
flask+gunicornなバックエンドでworker-classがデフォルトのsyncで同期処理をしていたのを非同期処理ができるように設定を変更しました。
同期処理の何が問題かというと、backendの処理に時間がかかる and プロセス数以上にリクエストがきてしまった場合、process数より多かった分のリクエストが待ち状態になりtimeoutになることがあります。
このような問題を解決すべくgeventを使い非同期で処理できるようにする方法をまとめました。
そもそもgunicornのワーカークラスには - sync - gevent - eventlet - tornado - gthread
と5つ存在していて今回はgeventを選択しました。geventはgreenletをベースとした非同期ワーカーです。
pip install gevent
でインストールでき,
起動時に-k WORKER_NAME
または--worker-class WORKER_NAME
のどちらかのオプションで指定すれば起動できます。 コードに対しての変更は特に必要ないです。
以下のように処理されます。
今回検証に使った簡易的なサーバとスクリプト
request script
import json import requests def register_name(self): url = 'http://127.0.0.1:5000/' res = requests.post(url) return res if __name__ == '__main__': result = register_name('test01')
proxy server
from flask import Flask import requests @app.route('/') def register(): url = 'https://127.0.0.1:5001' request.post(url) return "Created", 201 if __name__ == '__main__': app.run(processes=5, port=5000)
backend server
from flask import Flask app = Flask(__name__) @app.route('/') def wait_time(): time.sleep(60) return "Created", 201 if __name__ == '__main__': app.run(port=5001, processes=10)
変更後の注意
非同期にすることで裁く量が増える場合があるので、MySQLなど別のところで問題が発生する可能性があります。 そのため、事前にconnection数など確認しておくと良いかもしれません。