uWSGI+Flaskで、gevent.sleepが並行動作しない
uWSGI+FlaskのWebアプリをgeventを使って並行動作させようとしています。
具体的には時間がかかる外部IO処理をロングポーリング方式で実装しようとしており、
そのIO待ちをgevent.sleepで待機したいと考えています。
その前段階として、以下のコードでgevent.sleep動作確認したところ、期待と異なる結果となりました。
ソースコード
python
1# 必要なモジュールのimport, Flaskの設定等 2 3@app.route('/sleep1/<int:seconds>') 4def sleep1_response(seconds: int): 5 gevent.sleep(seconds) 6 return jsonify(sleep=seconds) 7 8 9def func(seconds, data): 10 gevent.sleep(seconds) 11 print(data) 12 13 14@app.route('/sleep2/<int:seconds>') 15def sleep2_response(seconds: int): 16 gevent.spawn(func, seconds, 'test') 17 return jsonify(sleep=seconds)
結果
- /sleep1/10 を同時に2つ開く -> 10秒後にひとつめ、20秒後にふたつめのページが表示される
- /sleep2/10 を同時に2つ開く -> ページはすぐに表示され、10秒後にuWSGIのログにtestが2つ表示される
解決したいこと
以上の結果から、 /sleep1/10 はsleep動作が並行動作しておらず、
/sleep2/10 はsleepが並行動作していると考えられます。
geventはgevent.sleepを呼ぶとコンテキストスイッチが起こるそうなので、
/sleep1/10 も並行動作することを期待したのですが、
なぜこのような動作となるのでしょうか?
また、Flaskのレスポンスをgevent.sleepで遅延させたい場合、
どのようにすれば良いでしょうか?
uWSGIの設定ファイル
ini
1[uwsgi] 2base = /path/to/foo 3chdir = %(base) 4module = webapp.view:app 5master = true 6processes = 2 7gevent = 1024 8socket = /tmp/uwsgi_foo.sock 9chmod-socket = 666 10vacuum = true 11die-on-term = true 12 13# ロギング 14logto = /var/log/uwsgi/foo.log 15log-maxsize = 10485760 16log-backupname = %(logto).1 17log-encoder = format ${strftime:%%Y/%%m/%%d %%H:%%M:%%S} - ${msgnl} 18ignore-sigpipe = true 19ignore-write-errors = true 20disable-write-exception = true 21 22harakiri = 90 # 処理のタイムアウト秒 23 24# 更新 25touch-reload = .uwsgi_touch
その他
- WebアプリはMySQLへの読み書き処理を含む
- MySQLの読み書きはSQLAlchemy+PyMySQLを使用している
- uWSGIのgevent-monkey-patchオプションを有効に有効にすると、SQLAlchemyで例外が発生するようになったため、モンキーパッチは使用していない (DBアクセス中にコネクションが切断される。scoped_sessionをgevent経由で並行アクセスするようになるのが原因?)
回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。