我试图了解如何实现gevent
的猴子补丁应该提供的异步优势。
要对此进行测试,我创建了一个测试服务器。
from gevent import monkey
monkey.patch_all()
from flask import Flask
from time import sleep
import requests
app = Flask(__name__)
def fib(n):
if n == 0:
return 0
elif n == 1:
return 1
else:
return fib(n - 1) + fib(n - 2)
@app.route('/')
def hello_world():
return 'Hello, World!'
@app.route('/sleep/<int:n>')
def sleep_view(n):
sleep(n)
return f'Slept {n}'
@app.route('/slowreq')
def slowreq_view():
res = requests.get('http://localhost:8002/sleep/5')
return 'From another server: ' + res.text
@app.route('/fib/<int:n>')
def fib_view(n):
x = fib(n)
return str(x)
if __name__ == '__main__':
import sys
port = 8001
threaded = False
if len(sys.argv) > 1:
port = int(sys.argv[1])
threaded = True
print(f'Threaded is {threaded}')
app.run(port=port, threaded=threaded)
如果我在两个进程中运行它,首先使用python3 test.py
(在8001上运行,flask是非线程的,但猴子已修补),然后在python3 test.py 8002
(运行在8002上,flask是线程的,也猴子打补丁),我希望会发生以下情况:
time curl http://localhost:8001/slowreq
。 /slowreq
在另一台服务器上调用/sleep/5
,因此作为一个独立的请求,需要5秒钟。requests.get
调用8002服务器。请求是urllib3
上的包装器,它是socket
上的stdlib包装器,默认情况下gevent.monkey.patch_all()
对其进行修补(默认为socket=True
)。由于采用了猴子修补程序,我期望服务器正在等待响应。/sleep/5
请求,休眠5秒钟,然后做出响应。因为它是线程服务器,所以可以同时发生多个睡眠。在非猴子补丁情况下,我希望第一个/slowreq
请求花费5秒,第二个请求花费10秒,这就是我所看到的。
但是,在采用猴子补丁的情况下,我希望8001服务器不会再因requests.get
调用而阻塞,因此两个请求都将花费5秒钟。不会发生这种情况,其行为与非猴子修补情况相同。
因此,我的问题是:猴子修补有什么作用?我如何利用它的好处?