Python 使用Flask和eventlet响应并发请求

Python 使用Flask和eventlet响应并发请求,python,flask,eventlet,flask-socketio,Python,Flask,Eventlet,Flask Socketio,我尝试设置一个最小的Flask应用程序,它使用即时响应并发请求,而不是一个接一个地阻塞和响应请求(就像标准的Flask调试Web服务器那样) 先决条件: pip install Flask pip install eventlet 根据我目前在互联网上的发现,它应该是这样工作的: # activate eventlet import eventlet eventlet.monkey_patch() from flask import Flask import datetime from t

我尝试设置一个最小的Flask应用程序,它使用即时响应并发请求,而不是一个接一个地阻塞和响应请求(就像标准的Flask调试Web服务器那样)

先决条件:

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秒后第一个选项卡完成后返回

这里怎么了? 顺便问一下,鉴于预期的并发用户很少(最多5个),这是否就是Flask通常所说的“生产就绪Web服务器”

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

烧瓶插座的完整示例:

# 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)
不会神奇地将您的代码变成一个可以异步处理请求的多线程野兽(它仍然非常神奇和可怕)

如中所示,您需要使用启动
wsgi
服务器

如果您想要一个标准的解决方案,可以看看如何使用nginx和uwsgi来启动flask应用程序。您可能还对利用创建完整多线程wsgi处理程序的痛苦的项目感兴趣。

当您运行
app.run(debug=True)
时,您明确地告诉Flask在基于Werkzeug的开发web服务器上运行您的应用程序。您是否已加载eventlet并不重要

如果要在eventlet web服务器上运行应用程序,必须启动eventlet web服务器,该服务器根据启动方式如下:

wsgi.server(eventlet.listen(('', 8000)), your_app)

这或多或少是
socketio.run()
在我的Flask socketio扩展中所做的事情,有选择地处理SSL稍微复杂一些。执行此操作的代码行为:。如果您环顾这些行,您将看到有三个不同的启动代码块,一个用于werkzeug,一个用于eventlet,另一个用于gevent。它们都不一样。

好吧,我明白了,切换到野兽模式并不是那么容易。然而,
flask socketio
如何处理这个问题呢?至少,在“Deployment/Embedded server”(部署/嵌入式服务器)下会显示
,请注意,在安装eventlet或gevent时,socketio.run(应用程序)会运行一个生产就绪的服务器。
,无需进一步详细说明。既然使用uWsgi/NGINX,那么像上面那样使用
flask socketio
有什么缺点吗?太好了!从eventlet文档中的示例中,我不清楚必须将Flask app对象传递给wsgi.server命令,因此这个基于Flask的示例非常有用。
wsgi.server(eventlet.listen(('', 8000)), your_app)