【问题标题】:Flask blocking on endpoint without allowing another endpoint callsFlask 在端点上阻塞而不允许另一个端点调用
【发布时间】:2020-05-28 02:21:15
【问题描述】:

我的烧瓶 API 的一个端点向直播流发出长请求。下面是代码示例:

@app.route('/stream')
def live_stream(sensor_id):
    stream = requests.get('stream_url', stream=True)
    return Response(stream_with_context(stream.iter_content(chunk_size=2048)),
                content_type=stream.headers['content-type'])

这条路线运行良好,溪流顺利。但是,当我尝试向其他路由发出请求时,服务器似乎卡在了这个端点。

我正在使用 gevent WSGI 服务器:

 http_server = WSGIServer(('0.0.0.0', 5000), app).serve_forever()

我正在从一个已经由 Flask 路由返回的模板发出请求。

我怎样才能向 API 发出并行请求而不会被卡住?

【问题讨论】:

  • 你能展示/描述stream_with_context内部发生的事情吗?
  • stream_with_context 是 Fl​​ask 的默认方法。直播是工作文件,但我无法提出更多请求。
  • 你做了猴子补丁吗,在这里提到:stackoverflow.com/questions/14551823/…

标签: python flask wsgi gevent


【解决方案1】:

我从未使用过 gevent,但如果我理解正确的话,它有一个单线程事件循环(如 asyncio)。但是我的理解可能是错误的。

看看这个答案https://stackoverflow.com/a/19153826/

当您有一段 python 代码需要很长时间(几秒钟)运行并且不会导致 greenlets 切换时,所有其他 greenlets / gevent 作业将“饿死”并且没有计算时间,它看起来像您的应用程序“挂起”。

我建议执行以下操作之一:

  • 或者,在线程化的 WSGI 服务器中运行您的 Web 应用程序
  • 或者,研究 gevent 是否有可以使用的网络客户端,而不是基于 greelets 的 requests
  • 或者,在线程工具中运行代码的阻塞部分
  • 或者,调用from gevent import monkey; monkey.patch_all() 作为服务器代码中的第一件事,看看这是否使requests 表现得非阻塞。

【讨论】:

  • 但是请求模块不是来自 Gevent。就是这个pypi.org/project/requests。你有什么建议用作 Gevent 的替代品吗?它必须在 Windows 操作系统上运行。
  • 先尝试使用flask的开发网络服务器。您可以将参数传递给app.run() 以使其运行多线程。
  • 它适用于烧瓶开发服务器!您知道如何将 eventlet WSGI 服务器设置为多线程吗?
  • eventlet WSGI 服务器是一个单线程服务器,我相信。您的选择是:使用线程服务器,或使用基于 greenlets 的方法执行网络请求,或在线程池中执行请求。
  • ... 添加了第四个选项:检查 gevent monkey-patching 是否使请求表现为非阻塞。
【解决方案2】:

您可以通过以下步骤进行检查:

  1. 确保你的代码在第一行是monkey patched(否则如果某些模块没有打补丁并且正在做一些 您的应用程序将阻塞的 I/O 操作。我记得gevent中有一个API可以检查monkey.is_module_patched('request'));
  2. 确保您没有执行一些 CPU 受限任务(CPU 受限代码会阻塞您的代码);

希望对您有所帮助!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-31
    • 2019-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多