python - 使用 Flask 和 eventlet 响应并发请求

标签 python flask eventlet flask-socketio

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

先决条件:

pip install Flask
pip install eventlet

根据我目前在 Internet 上找到的内容的理解,它应该像这样工作:

# 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,同时它仍在处理打开另一个带有 http://localhost:5000 的选项卡/shortTask,我希望第二个选项卡在第一个选项卡仍在加载时立即返回。然而,与在标准 Werkzeug 服务器上运行时类似,第二个选项卡仅在第一个选项卡完成 30 秒后才返回。

这里有什么问题? 顺便说一下,考虑到预期的并发用户很少(最多 5 个),这就是通常所说的 Flask 的“生产就绪网络服务器”吗?

顺便说一下,当我使用 the Flask-socketio library 时运行网络服务器,根据文档,如果安装了 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)

最佳答案

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

如果你想在 eventlet web 服务器上运行你的应用程序,你必须启动一个 eventlet web 服务器,根据 the documentation启动如下:

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

这或多或少是 socketio.run() 在我的 Flask-SocketIO 扩展中所做的,只是稍微复杂一点以选择性地处理 SSL。执行此操作的代码行是:https://github.com/miguelgrinberg/Flask-SocketIO/blob/539cd158f49ce085151911cb63edbacd0fa37173/flask_socketio/init.py#L391-L408 .如果你环顾这些行,你会发现有三种不同的启动代码块,一种用于 werkzeug,一种用于 eventlet,一种用于 gevent。它们各不相同。

关于python - 使用 Flask 和 eventlet 响应并发请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34722247/

相关文章:

python - 当我将它与 Selenium 一起使用时,PyQt 进度条不起作用

python - 这个针对Google Foobar "Re-ID"的解决方案可以更有效吗?

python - 后台线程记录到 Flask 应用程序中的服务器发送事件流

python - 如何在 Python eventlet 中停止协程/线程

python - Python多线程编程有什么优势?

python - 获取图像模式 PIL Python

python - 计算 Boyer-Moore 字符串搜索算法中的第二个(不匹配)表

python - 无法在 Google Cloud 应用程序上的 Flask 应用程序中流式传输 API 响应

mysql - 通过 AJAX 发送 POST 请求时 Console.log 显示 "500 (INTERNAL SERVER ERROR)"

python - eventlet 是否可以通过异步传入和传出的消息来管理 AMQP 连接?