Экспериментируя с некоторым асинхронным кодом, в Python 3.8.0 я наткнулся на следующую ситуацию. У меня есть client.py
, который может обрабатывать соединения асинхронно с сервером в server.py
. Этот сервер делает вид, что выполняет некоторую работу, но на самом деле спит несколько секунд, а затем возвращается. Мой вопрос заключается в том, что, поскольку сервер работает в совершенно другом процессе, почему имеет значение, блокирует ли спящий метод или нет, и если процессы на стороне сервера могут не блокировать, каково преимущество таких асинхронных вызовов в первое место?
# client.py
import time
import asyncio
import aiohttp
async def request_coro(url, session):
async with session.get(url) as response:
return await response.read()
async def concurrent_requests(number, url='http://localhost:8080'):
tasks = []
async with aiohttp.ClientSession() as session:
for n in range(number):
# Schedule the tasks
task = asyncio.create_task(request_coro(url, session))
tasks.append(task)
# returns when all tasks are completed
return await asyncio.gather(*tasks)
t0 = time.time()
responses = asyncio.run(concurrent_requests(10))
elapsed_concurrent = time.time() - t0
sum_sleeps = sum((int(i) for i in responses))
print(f'{elapsed_concurrent=:.2f} and {sum_sleeps=:.2f}')
# server.py
import time
import random
import logging
import asyncio
from aiohttp import web
random.seed(10)
async def index(requests):
# Introduce some latency at the server side
sleeps = random.randint(1, 3)
# NON-BLOCKING
# await asyncio.sleep(sleeps)
# BLOCKING
time.sleep(sleeps)
return web.Response(text=str(sleeps))
app = web.Application()
app.add_routes([web.get('/', index),
web.get('/index', index)])
logging.basicConfig(level=logging.DEBUG)
web.run_app(app, host='localhost', port=8080)
Это результаты 10 асинхронных вызовов клиента, использующих либо блокирующие, либо неблокирующие спящие методы:
asyncio. сон (неблокирующий)
elapsed_concurrent = 3,02 и sum_sleeps = 19,00
time.sleep (блокировка)
elapsed_concurrent = 19,04 и sum_sleeps = 19.00