最大化并行请求数(aiohttp)
Maximize number of parallel requests (aiohttp)
tl;dr:如何最大化可以并行发送的 http 请求数?
我正在使用 aiohttp
库从多个 url 中获取数据。我正在测试它的性能,我发现在这个过程中的某个地方存在瓶颈,运行一次 urls 只是无济于事。
我正在使用此代码:
import asyncio
import aiohttp
async def fetch(url, session):
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0'}
try:
async with session.get(
url, headers=headers,
ssl = False,
timeout = aiohttp.ClientTimeout(
total=None,
sock_connect = 10,
sock_read = 10
)
) as response:
content = await response.read()
return (url, 'OK', content)
except Exception as e:
print(e)
return (url, 'ERROR', str(e))
async def run(url_list):
tasks = []
async with aiohttp.ClientSession() as session:
for url in url_list:
task = asyncio.ensure_future(fetch(url, session))
tasks.append(task)
responses = asyncio.gather(*tasks)
await responses
return responses
loop = asyncio.get_event_loop()
asyncio.set_event_loop(loop)
task = asyncio.ensure_future(run(url_list))
loop.run_until_complete(task)
result = task.result().result()
运行 这具有不同长度的 url_list
(针对 https://httpbin.org/delay/2 的测试)我看到添加更多 urls一次 运行 最多只能帮助 ~100 urls 然后总时间开始与 urls 的数量成比例增长(或者换句话说,每个 url 不减少)。这表明在尝试一次处理这些时有些东西失败了。此外,在 'one batch' 中有更多 urls,我偶尔会收到连接超时错误。
- 为什么会这样?究竟是什么限制了速度?
- 我如何检查可以在给定计算机上发送的最大 并行请求数是多少? (我的意思是一个确切的数字 - 不是上面 'trial and error' 的大约)
- 我怎样才能增加一次处理的请求数量?
我运行在 Windows 上对此表示不满。
编辑 回复评论:
这是限制设置为 None
的相同数据。最后只有轻微的改善,并且有很多连接超时错误,一次发送 400 urls。我最终在实际数据上使用了 limit = 200
。
默认情况下 aiohttp
将同时连接数限制为 100
。它通过将默认 limit
设置为 TCPConnector
object 来实现,ClientSession
使用。您可以通过创建自定义连接器并将其传递给会话来绕过它:
connector = aiohttp.TCPConnector(limit=None)
async with aiohttp.ClientSession(connector=connector) as session:
# ...
但是请注意,您可能不想将此数字设置得太高:您的网络容量、CPU、RAM 和目标服务器都有其自身的限制,尝试建立大量连接可能会导致越来越多的失败。
最好的数字大概只能通过具体的机器实验才能找到。
无关:
没有 ,您不必创建任务。大多数 asyncio api 接受常规协程。例如,您的最后几行代码可以这样更改:
loop = asyncio.get_event_loop()
loop.run_until_complete(run(url_list))
如果您使用 Python 3.7
,甚至只是 asyncio.run(run(url_list))
(doc)
tl;dr:如何最大化可以并行发送的 http 请求数?
我正在使用 aiohttp
库从多个 url 中获取数据。我正在测试它的性能,我发现在这个过程中的某个地方存在瓶颈,运行一次 urls 只是无济于事。
我正在使用此代码:
import asyncio
import aiohttp
async def fetch(url, session):
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.3; Win64; x64; rv:64.0) Gecko/20100101 Firefox/64.0'}
try:
async with session.get(
url, headers=headers,
ssl = False,
timeout = aiohttp.ClientTimeout(
total=None,
sock_connect = 10,
sock_read = 10
)
) as response:
content = await response.read()
return (url, 'OK', content)
except Exception as e:
print(e)
return (url, 'ERROR', str(e))
async def run(url_list):
tasks = []
async with aiohttp.ClientSession() as session:
for url in url_list:
task = asyncio.ensure_future(fetch(url, session))
tasks.append(task)
responses = asyncio.gather(*tasks)
await responses
return responses
loop = asyncio.get_event_loop()
asyncio.set_event_loop(loop)
task = asyncio.ensure_future(run(url_list))
loop.run_until_complete(task)
result = task.result().result()
运行 这具有不同长度的 url_list
(针对 https://httpbin.org/delay/2 的测试)我看到添加更多 urls一次 运行 最多只能帮助 ~100 urls 然后总时间开始与 urls 的数量成比例增长(或者换句话说,每个 url 不减少)。这表明在尝试一次处理这些时有些东西失败了。此外,在 'one batch' 中有更多 urls,我偶尔会收到连接超时错误。
- 为什么会这样?究竟是什么限制了速度?
- 我如何检查可以在给定计算机上发送的最大 并行请求数是多少? (我的意思是一个确切的数字 - 不是上面 'trial and error' 的大约)
- 我怎样才能增加一次处理的请求数量?
我运行在 Windows 上对此表示不满。
编辑 回复评论:
这是限制设置为 None
的相同数据。最后只有轻微的改善,并且有很多连接超时错误,一次发送 400 urls。我最终在实际数据上使用了 limit = 200
。
默认情况下 aiohttp
将同时连接数限制为 100
。它通过将默认 limit
设置为 TCPConnector
object 来实现,ClientSession
使用。您可以通过创建自定义连接器并将其传递给会话来绕过它:
connector = aiohttp.TCPConnector(limit=None)
async with aiohttp.ClientSession(connector=connector) as session:
# ...
但是请注意,您可能不想将此数字设置得太高:您的网络容量、CPU、RAM 和目标服务器都有其自身的限制,尝试建立大量连接可能会导致越来越多的失败。
最好的数字大概只能通过具体的机器实验才能找到。
无关:
没有
loop = asyncio.get_event_loop()
loop.run_until_complete(run(url_list))
如果您使用 Python 3.7
,甚至只是asyncio.run(run(url_list))
(doc)