使用 Gunicorn 和 Gevent 在 运行 Flask 时使用 requests 进行非阻塞请求
Make a non-blocking request with requests when running Flask with Gunicorn and Gevent
我的 Flask 应用程序将接收一个请求,进行一些处理,然后向一个需要 5 秒响应的慢速外部端点发出请求。看起来 运行 Gunicorn with Gevent 将允许它同时处理许多这些缓慢的请求。我怎样才能修改下面的例子,使视图是非阻塞的?
import requests
@app.route('/do', methods = ['POST'])
def do():
result = requests.get('slow api')
return result.content
gunicorn server:app -k gevent -w 4
您可以使用 grequests
。它允许其他 greenlets 在发出请求时 运行。它与 requests
库和 returns 一个 requests.Response
对象兼容。用法如下:
import grequests
@app.route('/do', methods = ['POST'])
def do():
result = grequests.map([grequests.get('slow api')])
return result[0].content
编辑:我添加了一个测试,发现 grequests 的时间没有改善,因为 gunicorn 的 gevent worker 在初始化时已经执行了猴子修补:https://github.com/benoitc/gunicorn/blob/master/gunicorn/workers/ggevent.py#L65
首先介绍一下背景知识,阻塞套接字是默认类型的套接字,一旦您开始读取您的应用程序或线程,直到数据被实际读取或您断开连接时才会重新获得控制权。这就是 python-requests
默认的操作方式。有一个名为 grequests
的副产品,它提供非阻塞读取。
The major mechanical difference is that send, recv, connect and accept
can return without having done anything. You have (of course) a number
of choices. You can check return code and error codes and generally
drive yourself crazy. If you don’t believe me, try it sometime
来源:https://docs.python.org/2/howto/sockets.html
还接着说:
There’s no question that the fastest sockets code uses non-blocking
sockets and select to multiplex them. You can put together something
that will saturate a LAN connection without putting any strain on the
CPU. The trouble is that an app written this way can’t do much of
anything else - it needs to be ready to shuffle bytes around at all
times.
Assuming that your app is actually supposed to do something more than
that, threading is the optimal solution
但是您是否希望通过生成自己的线程来增加视图的复杂性。特别是当 gunicorn 为 async workers?
The asynchronous workers available are based on Greenlets (via
Eventlet and Gevent). Greenlets are an implementation of cooperative
multi-threading for Python. In general, an application should be able
to make use of these worker classes with no changes.
和
Some examples of behavior requiring asynchronous workers: Applications
making long blocking calls (Ie, external web services)
长话短说,不要改变任何东西!随它去吧。如果您要进行任何更改,请引入缓存。考虑使用 Cache-control python 推荐的扩展-请求开发人员。
如果您使用 gunicorn 部署 Flask 应用程序,它已经是非阻塞的。如果客户端正在等待来自您的一个视图的响应,则另一个客户端可以毫无问题地向同一视图发出请求。会有多个worker同时处理多个请求。无需更改您的代码即可使其正常工作。这也适用于几乎所有 Flask 部署选项。
我的 Flask 应用程序将接收一个请求,进行一些处理,然后向一个需要 5 秒响应的慢速外部端点发出请求。看起来 运行 Gunicorn with Gevent 将允许它同时处理许多这些缓慢的请求。我怎样才能修改下面的例子,使视图是非阻塞的?
import requests
@app.route('/do', methods = ['POST'])
def do():
result = requests.get('slow api')
return result.content
gunicorn server:app -k gevent -w 4
您可以使用 grequests
。它允许其他 greenlets 在发出请求时 运行。它与 requests
库和 returns 一个 requests.Response
对象兼容。用法如下:
import grequests
@app.route('/do', methods = ['POST'])
def do():
result = grequests.map([grequests.get('slow api')])
return result[0].content
编辑:我添加了一个测试,发现 grequests 的时间没有改善,因为 gunicorn 的 gevent worker 在初始化时已经执行了猴子修补:https://github.com/benoitc/gunicorn/blob/master/gunicorn/workers/ggevent.py#L65
首先介绍一下背景知识,阻塞套接字是默认类型的套接字,一旦您开始读取您的应用程序或线程,直到数据被实际读取或您断开连接时才会重新获得控制权。这就是 python-requests
默认的操作方式。有一个名为 grequests
的副产品,它提供非阻塞读取。
The major mechanical difference is that send, recv, connect and accept can return without having done anything. You have (of course) a number of choices. You can check return code and error codes and generally drive yourself crazy. If you don’t believe me, try it sometime
来源:https://docs.python.org/2/howto/sockets.html
还接着说:
There’s no question that the fastest sockets code uses non-blocking sockets and select to multiplex them. You can put together something that will saturate a LAN connection without putting any strain on the CPU. The trouble is that an app written this way can’t do much of anything else - it needs to be ready to shuffle bytes around at all times.
Assuming that your app is actually supposed to do something more than that, threading is the optimal solution
但是您是否希望通过生成自己的线程来增加视图的复杂性。特别是当 gunicorn 为 async workers?
The asynchronous workers available are based on Greenlets (via Eventlet and Gevent). Greenlets are an implementation of cooperative multi-threading for Python. In general, an application should be able to make use of these worker classes with no changes.
和
Some examples of behavior requiring asynchronous workers: Applications making long blocking calls (Ie, external web services)
长话短说,不要改变任何东西!随它去吧。如果您要进行任何更改,请引入缓存。考虑使用 Cache-control python 推荐的扩展-请求开发人员。
如果您使用 gunicorn 部署 Flask 应用程序,它已经是非阻塞的。如果客户端正在等待来自您的一个视图的响应,则另一个客户端可以毫无问题地向同一视图发出请求。会有多个worker同时处理多个请求。无需更改您的代码即可使其正常工作。这也适用于几乎所有 Flask 部署选项。