为了账号安全,请及时绑定邮箱和手机立即绑定

asyncio + aiohttp:IO 与睡眠重叠

asyncio + aiohttp:IO 与睡眠重叠

子衿沉夜 2021-08-17 09:53:52
当所有协程都在等待时,asyncio 会监听事件以再次唤醒它们。一个常见的例子是asyncio.sleep(),它注册一个定时事件。在实践中,事件通常是准备接收或发送新数据的 IO 套接字。为了更好地理解这种行为,我设置了一个简单的测试:它向 localhost 发送一个 http 请求并等待响应。在本地主机上,我设置了一个在响应前等待 1 秒的 Flask 服务器。发送请求后,客户端休眠 1 秒,然后等待响应。我希望这会在一秒钟内返回,因为我的程序和服务器都应该并行睡眠。但是需要2秒:import aiohttpimport asynciofrom time import perf_counterasync def main():    async with aiohttp.ClientSession() as session:        # this http request will take 1 second to respond        async with session.get("http://127.0.0.1:5000/") as response:            # yield control for 1 second            await asyncio.sleep(1)            # wait for the http request to return            text = await response.text()            return textloop = asyncio.get_event_loop()start = perf_counter()results = loop.run_until_complete(main())stop = perf_counter()print(f"took {stop-start} seconds") # 2.01909asyncio 在这里做什么,为什么我不能重叠等待时间?我对HTTP请求的具体场景不感兴趣,aiohttp只是用来构造一个例子。这可能有点危险:这可能与 aiohttp 而不是 asyncio 有关。实际上,我希望是这种情况(因此是关于 asyncio 和 aiohttp 的问题标题)。我的第一个直觉是在调用之前可能没有发送请求asyncio.sleep().所以我重新排序了一些东西:# start coroutinetext = response.text()# yield control for 1 secondawait asyncio.sleep(1)# wait for the http request to returntext = await text但这仍然需要两秒钟。好的,现在要确定请求是在进入睡眠之前发送的,我print("incoming")在它进入睡眠之前添加到服务器上的路由。我还将客户端的睡眠时间长度更改为 10 秒。服务器在客户端运行后立即打印传入。客户端总共需要 11 秒。@app.route('/')def index():    print("incoming")    time.sleep(1)    return 'done'由于 HTTP 请求是立即发出的,因此服务器肯定在客户端唤醒之前发送了一个答案。在asyncio.sleep().我看来,提供 HTTP 请求的套接字应该在客户端唤醒后立即准备就绪。但是,总运行时间始终是客户端和服务器等待时间的增加。我是否以某种方式滥用 asyncio,或者这毕竟与 aiohttp 有关?
查看完整描述

2 回答

  • 2 回答
  • 0 关注
  • 140 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信