tl; dr :如何最大化可并行发送的http请求的数量?
我正在使用aiohttp
库从多个URL中获取数据。我正在测试其性能,并且发现该过程中的某个地方存在瓶颈,即一次运行更多url并没有帮助。
我正在使用以下代码:
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 进行测试),我发现一次添加更多要运行的网址最多只能提供约100个网址,然后总时间开始与网址数量成正比增长(换句话说,每个网址的时间不会减少)。这表明尝试立即处理这些操作时某些操作失败。此外,“一批”中有更多url,我偶尔会收到连接超时错误。
我在Windows上运行。
编辑以回复评论:
这是相同的数据,其限制设置为None
。最后仅稍有改进,一次发送400个URL时有许多连接超时错误。我最终在我的实际数据上使用了limit = 200
。
答案 0 :(得分:3)
默认情况下,aiohttp
将同时连接的数量限制为100
。它可以通过将limit
使用的默认TCPConnector
设置为ClientSession
object来实现。您可以通过创建自定义连接器并将其传递到会话来绕过它:
connector = aiohttp.TCPConnector(limit=None)
async with aiohttp.ClientSession(connector=connector) as session:
# ...
但是请注意,您可能不想将此数字设置得太高:您的网络容量,CPU,RAM和目标服务器有其自身的限制,并尝试进行大量连接会导致故障增加。
最佳数量可能只能通过在混凝土机器上进行实验才能找到。
无关:
没有reason,您不必创建任务。大多数异步api接受常规协程。例如,您的最后几行代码可以通过以下方式更改:
loop = asyncio.get_event_loop()
loop.run_until_complete(run(url_list))
如果您使用的是Python 3.7,甚至只是asyncio.run(run(url_list))
(doc)