Ответ на параллельные запросы с помощью Flask и eventlet
Я пытаюсь настроить минимальное приложение колбы, которое использует eventlet мгновенно реагировать на параллельные запросы, а не блокировать и отвечать на один запрос за другим (как это делает стандартный веб-сервер отладки колбы).
требования:
pip install Flask
pip install eventlet
из моего понимания, что я нашел до сих пор в интернете, он должен работать так:
# activate eventlet
import eventlet
eventlet.monkey_patch()
from flask import Flask
import datetime
from time import sleep
# create a new Flask application
app = Flask(__name__)
# a short running task that returns immediately
@app.route('/shortTask')
def short_running_task():
start = datetime.datetime.now()
return 'Started at {0}, returned at {1}'.format(start, datetime.datetime.now())
# a long running tasks that returns after 30s
@app.route('/longTask')
def long_running_task():
start = datetime.datetime.now()
sleep(30)
return 'Started at {0}, returned at {1}'.format(start, datetime.datetime.now())
# run the webserver
if __name__ == '__main__':
app.run(debug=True)
при запуске этого файла, то открывающий тег http://localhost:5000/longTask
на вкладке webbrowser и пока он все еще обрабатывает открытие другой вкладки с http://localhost:5000/shortTask
, Я ожидал бы, что вторая вкладка вернется немедленно, пока первая вкладка все еще загружается. Однако, как и при запуске этого на стандартном сервере Werkzeug, вторая вкладка возвращается только после того, как первая завершена после 30-х годов.
что здесь не так? Кстати, будет ли это то, что обычно называют "готовым к производству веб-сервером" для Flask, учитывая, что есть только несколько одновременных пользователей ожидается (5 максимум)?
кстати, когда я использую колбу-socketio библиотека для запуска веб-сервера, который, согласно документации, автоматически выбирает eventlet, если он установлен, то он работает так, как ожидалось.
полный пример с колбой-socketio:
# activate eventlet
import eventlet
eventlet.monkey_patch()
from flask import Flask
from flask_socketio import SocketIO
import datetime
from time import sleep
# create a new Flask application
app = Flask(__name__)
# activate Flask-socketio
socketio = SocketIO(app)
# a short running task that returns immediately
@app.route('/shortTask')
def short_running_task():
start = datetime.datetime.now()
return 'Started at {0}, returned at {1}'.format(start, datetime.datetime.now())
# a long running tasks that returns after 30s
@app.route('/longTask')
def long_running_task():
start = datetime.datetime.now()
sleep(30)
return 'Started at {0}, returned at {1}'.format(start, datetime.datetime.now())
# run the webserver with socketio
if __name__ == '__main__':
socketio.run(app, debug=True)
2 ответов
при выполнении app.run(debug=True)
вы явно говорите Flask запустить приложение на веб-сервере разработки, который основан на Werkzeug. Не имеет значения, что вы загрузили eventlet.
Если вы хотите запустить приложение на веб-сервере eventlet, вы должны запустить веб-сервер eventlet, который в соответствии с документация запускается следующим образом:
wsgi.server(eventlet.listen(('', 8000)), your_app)
Это более или менее то, что socketio.run()
делает в моей колбе-расширение SocketIO, с немного большей сложностью дополнительно обрабатывать SSL. Строк кода, которые делают это, являются: https://github.com/miguelgrinberg/Flask-SocketIO/blob/539cd158f49ce085151911cb63edbacd0fa37173/flask_socketio/init.py#L391-L408. Если вы посмотрите вокруг этих линий, вы увидите, что есть три разных запуске куски кода, один для сверла, для eventlet и gevent для. Они все разные.
import eventlet
eventlet.monkey_patch()
не превратит ваш код в многопоточного зверя, который может обрабатывать запрос асинхронно (это все еще довольно волшебно и потрясающе).
Как вы можете видеть в , вам нужно запустить wsgi
сервер с помощью реализация eventlet wsgi.
Если вы хотите стандартное решение, посмотрите, как использовать nginx и uwsgi для запуска приложения flask. Вы также можете быть заинтересованы в проекте нерестовые это усиливает боль создания полного многопоточного обработчика wsgi.