python flask如何解决同时请求同一个请求的阻塞问题?

from flask import Flask
import time

app = Flask(__name__)

@app.route('/test)
def sayHello():
    time.sleep(10)
    return 'hello'

@app.route('/hi')
def sayHi():
    return 'hi'
if __name__ =='__main__'
    app.run(debug=True,threaded = True)

如上述代码所示,倘若在浏览器打开多张空白页,然后都去请求 127.0.0.1:5000/test ,会发现进入了阻塞状态,每一张页面会等待它之前的那个请求结束后在加载当前页面。但是去访问 127.0.0.1:5000/hi 却不会收到前面那个网址的影响

所以,我应该如何实现 我多个请求去访问 127.0.0.1:5000/test 这个不受其他的影响,能够同时加载?

阅读 17.1k
5 个回答

可以用gevet啊

from gevent import monkey
from gevent.pywsgi import WSGIServer
monkey.patch_all()
from flask import Flask
import time

app = Flask(__name__)

@app.route('/test',methods=['GET'])
def sayHello():
    time.sleep(10)
    return 'hello'

@app.route('/hi',methods=['GET'])
def sayHi():
    return 'hi'
if __name__ =='__main__':
    http_server = WSGIServer(('', 5000), app)
    http_server.serve_forever()

测试结果:
127.0.0.1 - - [2017-12-12 22:35:10] "GET /test/ HTTP/1.1" 200 126 0.000000
127.0.0.1 - - [2017-12-12 22:35:11] "GET /test/ HTTP/1.1" 200 126 0.000000
127.0.0.1 - - [2017-12-12 22:35:11] "GET /test/ HTTP/1.1" 200 126 0.000000
127.0.0.1 - - [2017-12-12 22:35:12] "GET /test/ HTTP/1.1" 200 126 0.000000
127.0.0.1 - - [2017-12-12 22:35:12] "GET /test/ HTTP/1.1" 200 126 0.000998
127.0.0.1 - - [2017-12-12 22:35:13] "GET /test/ HTTP/1.1" 200 126 0.001001
127.0.0.1 - - [2017-12-12 22:35:14] "GET /test/ HTTP/1.1" 200 126 0.000000
127.0.0.1 - - [2017-12-12 22:35:14] "GET /test/ HTTP/1.1" 200 126 0.001014
127.0.0.1 - - [2017-12-12 22:35:15] "GET /test/ HTTP/1.1" 200 126 0.001000
127.0.0.1 - - [2017-12-12 22:35:15] "GET /test/ HTTP/1.1" 200 126 0.000000
127.0.0.1 - - [2017-12-12 22:35:18] "GET /asyn/ HTTP/1.1" 200 126 10.000392

我认为访问hi也会受到test的影响。
言归正传,你可以使用gevent,在文件开头:

from gevent import monkey
monkey.patch_all()

正是部署的时候,建议用nginx+uwsgi+flask的形式。

后来发现了问题,因为我用都是chrome浏览器。如果我每次请求的参数,url等任何元素都是相同的,浏览器会判定为这两个时为同一个请求,所以当前一个请求没有结束的时候 后一个一模一样的请求也不能产生结果。但是在Python的flask当中,他默认是单线程,就是只能一个一个请求来处理,通过gevent等框架可以并发地处理请求,而gunicorn作为httpserver来启动程序时,相当于是多进程的所以也能够同时处理很多请求(这是我自己的理解,如果有不对的地方请支教!)

协程

import asyncio
import threading
import os
from aiohttp import web
routes = web.RouteTableDef()
@routes.get('/')
async def index(request):
    # 耗时的io操作
    await asyncio.sleep(6)
    text = 'pid  %d , <br> threading %s  <br> request  %d ' % (
        os.getpid(), threading.current_thread().name, id(request))
    return web.Response(body=text, content_type='text/html')
app = web.Application()
app.add_routes(routes)
web.run_app(app, host='127.0.0.1', port=6060)

单线程,多线程,多进程

import time
import threading
import os
from flask import Flask, request
app = Flask(__name__)
@app.route('/', methods=['GET', 'POST'])
def home():
    time.sleep(7)
    text = 'pid  %d , <br> threading %s  <br> request  %d ' % (
        os.getpid(), threading.current_thread().name, id(request))
    return text
if __name__ == '__main__':
    # 多进程
    app.run(host="127.0.0.1", port=8000, processes=4, threaded=False)
    # 多线程
    app.run(host="127.0.0.1", port=8000, threaded=True)
    # 单线程,process默认为1
    app.run(host="127.0.0.1", port=8080, threaded=False)

结果

多进程、多线程、协程 在不同浏览器都访问相同的router不阻塞。
多进程、多线程、协程、单线程 在相同浏览器都访问相同的router都阻塞。
不同的router怎么样都不阻塞,除了在单线程的情况下。

原因

浏览器搞的鬼,浏览器判断为同样的request后,上一个request请求返回后才继续请求。有一个队列。

证明

wget http://127.0.0.1:8000/ 
wget http://127.0.0.1:8000/ 

两次时间是一样的

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题