pie*_*eca 4 python asynchronous request python-asyncio aiohttp
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()
Run Code Online (Sandbox Code Playgroud)
以url_list不同的长度运行这个(针对https://httpbin.org/delay/2 的测试)我看到添加更多的 url 一次运行最多只能帮助大约 100 个 url,然后总时间开始与数量成正比增长urls(或者换句话说,每个 url 的时间不会减少)。这表明在尝试立即处理这些时会出现问题。此外,在“一批”中有更多网址时,我偶尔会收到连接超时错误。
我在 Windows 上运行这个。
编辑以回应评论:
这是限制设置为 的相同数据None。最后只有轻微的改进,并且一次发送了 400 个 url 的连接超时错误很多。我最终使用limit = 200了我的实际数据。
默认情况下aiohttp,同时连接数限制为100. 它实现了默认设置limit到TCPConnector 对象所使用ClientSession。您可以通过创建自定义连接器并将其传递给会话来绕过它:
connector = aiohttp.TCPConnector(limit=None)
async with aiohttp.ClientSession(connector=connector) as session:
# ...
Run Code Online (Sandbox Code Playgroud)
但是请注意,您可能不想将此数字设置得太高:您的网络容量、CPU、RAM 和目标服务器都有自己的限制,尝试进行大量连接可能会导致故障增加。
可能只有通过在混凝土机器上的实验才能找到最佳数量。
无关:
您不必无故创建任务。大多数 asyncio api 接受常规协程。例如,您的最后几行代码可以这样修改:
loop = asyncio.get_event_loop()
loop.run_until_complete(run(url_list))
Run Code Online (Sandbox Code Playgroud)
或者甚至只是asyncio.run(run(url_list))( doc ) 如果您使用的是 Python 3.7
| 归档时间: |
|
| 查看次数: |
3626 次 |
| 最近记录: |