2016-01-28 69 views
10

tl; dr一个用route装饰的方法无法处理并发请求,而Flask在多个worker和线程启动的gunicorn之后服务,而两个不同的方法处理并发请求的罚款。为什么会出现这种情况,同一条路线如何同时投放?如何让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正在使用一个线程运行一个工人。

如果通过任一运行此:

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

在这种情况下,在两个不同的接片开放/foo/bar都采取5秒。这是有道理的,因为gunicorn正在运行一个有两个线程的工作者,或者两个工作者各有一个线程,并且可以同时提供两条线路。

但是,如果我同时打开两个/foo,不管gunicorn的配置如何,第二个标签总是需要10秒。

我怎样才能得到route装饰同样的方法来服务于并发请求?

回答

9

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

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

其结果是,即使使用异步工人像eventlet不会帮助:异步工人可以同时处理多个连接,但是当两个请求,相同的连接陆地上那么他们一定会被处理,一个接一个。

+1

有趣的是,最初这种浏览器的连接行为是为了通过避免建立新连接的额外开销来加速加载。但在这种情况下(服务器端处理速度缓慢),我们发现它可能会导致速度放缓。 – MarSoft

+0

我刚刚尝试过Chrome中的一个标签和Firefox中的一个标签,并收到了预期的结果。谢谢你,好的电话。 –

相关问题