在 aiobotocore 响应 ['Body'].read(...) 上看到挂起(无超时)

Seeing hangs (no timeout) on aiobotocore response['Body'].read(...)

使用 aiobotocore 创建客户端使用:

import botocore
import aiobotocore

s3_session = aiobotocore.get_session(loop=loop)
client = s3_session.create_client(
    's3',
    config=botocore.client.Config(connect_timeout=10, read_timeout=10, retries={'max_attempts': 0}),
    endpoint_url=endpoint_url,
)

稍后我得到了一个以 8k 块读取的异步函数:

async def aio_read(bucket, key, range_header):
    s3_object = await self.client.get_object(Bucket=bucket, Key=key, Range=range_header)
    s3_iostream = s3_object['Body']

    b = None
    body_data = b''
    while b != b'':
        b = await s3_iostream.read(8192)
        body_data += b
        print('{}> len(b) / len(body_data) = {}/{}'.format(uuid, len(b), len(body_data)))

我正在测试的下载大小为 1MB,以 8k 块读取。当我 运行 100 个并行进程时,我通常会挂起一些进程,并且通过上面的 print 语句,我可以看到其中一个 aio_read 函数在读取文件的过程中停止了.

正文读取操作似乎超时,然后无限期挂起。

如果发生读取超时,是否有办法从 aiobotocore 中获取异常?

这里的问题是超时是每个协程的,你不应该在一个协程中多次迭代读取,而你应该将多个协程提交给事件线程 运行 read多次。对于大文件,您也无法一次读取整个文件。对我来说效果很好的方法是将单独的协程提交给偶数循环,每个协程从 Body iostream 读取 1MB 的块。这样你就不会得到在 1 个协程内超时的大文件,也不会得到大量的协程,这些协程最终会产生开销并在事件循环(1 个线程,1 个核心)上消耗太多时间最大值),8k 太小了。