Я пытаюсь понять, как добиться асинхронных преимуществ, которые должна обеспечить 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, колба не резьбовая, но исправлена обезьяна), а затем python3 test.py 8002
(работает на 8002, колба резьбовая, также исправлена обезьяна),Я ожидаю, что произойдет следующее:
- В двух терминалах я быстро запускаю
time curl http://localhost:8001/slowreq
один за другим./slowreq
вызывает /sleep/5
на другом сервере, поэтому для отдельного запроса это должно занять 5 секунд. - Сервер на 8001 получает запрос и вызывает сервер 8002 с помощью
requests.get
.Requests - это оболочка для urllib3
, которая является оболочкой stdlib для socket
, которая gevent.monkey.patch_all()
исправляет по умолчанию (socket=True
по умолчанию).Из-за мартовских патчей я ожидаю, что сервер будет ожидать ответа. - Сервер 8002 получает запрос
/sleep/5
, спит в течение 5 секунд и отвечает.Поскольку это многопоточный сервер, одновременно может происходить несколько снов.
В случае, не являющемся пропатченным, я ожидаю, что первый запрос /slowreq
займет 5 секунд, а второйчтобы занять 10 секунд, и это то, что я вижу.
Однако, в случае с пропатченной обезьяной, я ожидаю, что сервер 8001 больше не будет блокировать вызов requests.get
, и поэтому оба запроса будут занимать 5секунд.Это не то, что происходит, и поведение идентично случаю, не пропатченному обезьянами.
Таким образом, мой вопрос: чего добивается исправление обезьяны и как я могу воспользоваться его преимуществами?