使用Flask和eventlet响应并发请求

Dir*_*irk 10 python flask eventlet flask-socketio

我尝试设置一个最小的Flask应用程序,该应用程序使用eventlet立即响应并发请求,而不是阻塞并响应一个请求(如标准的Flask调试Web服务器那样).

先决条件:

pip install Flask
pip install eventlet
Run Code Online (Sandbox Code Playgroud)

从我到目前为止在互联网上发现的东西的理解,它应该像这样工作:

# 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)
Run Code Online (Sandbox Code Playgroud)

运行此文件时,然后http://localhost:5000/longTask在webbrowser选项卡中打开,当它仍处理打开另一个选项卡时http://localhost:5000/shortTask,我希望第二个选项卡在第一个选项卡仍在加载时立即返回.但是,与在标准Werkzeug服务器上运行此类似时,第二个选项卡仅在第一个选项卡在30秒后完成后才返回.

这有什么不对?那么,对于Flask来说,这通常被称为"生产就绪的网络服务器",假设只有很少的并发用户(最多5个)?

顺便说一句,当我使用Flask-socketio库运行web服务器时,根据文档,如果安装了eventlet,它会自动选择eventlet,然后按预期工作.

Flask-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)
Run Code Online (Sandbox Code Playgroud)

Mig*_*uel 14

当您运行时,app.run(debug=True)您明确告诉Flask在开发Web服务器上运行您的应用程序,该服务器基于Werkzeug.加载eventlet没关系.

如果要在eventlet Web服务器上运行应用程序,则必须启动一个eventlet Web服务器,该服务器根据文档启动如下:

wsgi.server(eventlet.listen(('', 8000)), your_app)
Run Code Online (Sandbox Code Playgroud)

这或多或少socketio.run()都与我的Flask-SocketIO扩展有关,可选择处理SSL的复杂程度稍高.的代码,做到这一点的线路有:https://github.com/miguelgrinberg/Flask-SocketIO/blob/539cd158f49ce085151911cb63edbacd0fa37173/flask_socketio/ 初始化的.py#L391-L408.如果你环顾这些行,你会发现有三个不同的启动代码块,一个用于werkzeug,一个用于eventlet,一个用于gevent.他们都是不同的.

  • 出色的!从 eventlet 文档中的示例中,我不清楚必须将 Flask 应用程序对象传递给“wsgi.server”命令,因此这个基于 Flask 的示例非常有帮助。 (2认同)