如何让Flask / Gunicorn处理同一路由的并发请求?

时间:2016-01-28 01:49:00

标签: python flask gunicorn

tl; dr route修饰的方法无法处理并发请求,而Flask是在多个工作线程和线程启动的gunicorn后面提供的,而两个不同的方法处理并发请求很好。为什么会出现这种情况,如何同时提供相同的路由呢?

我有这个简单的烧瓶应用程序:

from flask import Flask, jsonify
import time
app = Flask(__name__)

@app.route('/foo')
def foo():
    time.sleep(5)
    return jsonify({'success': True}), 200

@app.route('/bar')
def bar():
    time.sleep(5)
    return jsonify({'success': False}), 200

如果我通过以下方式运行:

gunicorn test:app -w 1 --threads 1

如果我在浏览器的两个不同标签中快速打开/bar/foo,我先点击输入的标签将在5秒后加载,第二个标签将在10秒内加载。这是有道理的,因为gunicorn正在运行一个带有一个线程的worker。

如果我通过以下方式运行:

gunicorn test:app -w 1 --threads 2
gunicorn test:app -w 2 --threads 1

在这种情况下,在两个不同的标签页中打开/foo/bar都需要5秒钟。这是有道理的,因为gunicorn运行的是一个有两个线程的工作者,或者两个工作者,每个都有一个线程,并且可以同时为这两条路径提供服务。

但是,如果我同时打开两个/foo,无论枪械配置如何,第二个标签总是需要10秒。

如何获得由route修饰的同一方法来处理并发请求?

1 个答案:

答案 0 :(得分:9)

这个问题可能不是由Gunicorn或Flask引起的,而是由浏览器造成的。 我只是想重现它。有两个Firefox标签,它可以工作;但是如果我在不同的控制台中运行两个curl进程,那么它们将按预期(并行)获得服务,并且它们的请求由不同的工作人员处理 - 这可以通过在启动gunicorn时启用--log-level DEBUG来检查。 / p>

我认为这是因为Firefox(可能还有其他浏览器)为每个URL打开一个到服务器的连接;当您在两个选项卡上打开一个页面时,它们的请求将通过相同的(保持活动状态)连接发送,因此会发送给同一个工作人员。

因此,即使使用像eventlet这样的异步工作程序也无济于事:异步工作者可以一次处理多个连接,但当两个请求落在同一个连接上时,它们将会必须一个接一个地处理。