aiohttp 错误率随着连接数的增加而增加
aiohttp Error Rate Increases with Number of Connections
我正在尝试从数百万个不同的站点获取状态代码,我正在使用 asyncio 和 aiohttp,我 运行 下面的代码具有不同数量的连接(但请求超时相同)但是得到非常不同的结果,特别是以下异常的数量要多得多。
'concurrent.futures._base.TimeoutError'
密码
import pandas as pd
import asyncio
import aiohttp
out = []
CONNECTIONS = 1000
TIMEOUT = 10
async def fetch(url, session, loop):
try:
async with session.get(url,timeout=TIMEOUT) as response:
res = response.status
out.append(res)
return res
except Exception as e:
_exception = 'Error: '+str(type(e))
out.append(_exception)
return _exception
async def bound_fetch(sem, url, session, loop):
async with sem:
await fetch(url, session, loop)
async def run(urls, loop):
tasks = []
sem = asyncio.Semaphore(value=CONNECTIONS,loop=loop)
_connector = aiohttp.TCPConnector(limit=CONNECTIONS, loop=loop)
async with aiohttp.ClientSession(connector=_connector,loop=loop) as session:
for url in urls:
task = asyncio.ensure_future(bound_fetch(sem, url, session, loop))
tasks.append(task)
responses = await asyncio.gather(*tasks,return_exceptions=True)
return responses
## BEGIN ##
tlds = open('data/sample_1k.txt').read().splitlines()
urls = ['http://{}'.format(x) for x in tlds[1:]]
loop = asyncio.get_event_loop()
future = asyncio.ensure_future(run(urls,loop))
ans = loop.run_until_complete(future)
print(str(pd.Series(out).value_counts()))
结果
CONNECTIONS=1000
CONNECTIONS=100
这是一个错误吗?这些站点确实以状态代码和 运行 顺序响应,或者在连接较低的情况下没有超时错误,那么为什么会发生这种情况?当您更改连接数时,其他异常似乎很稳定。 ClientOSErrors 来自实际超时或响应的站点,老实说并不知道 concurrent.futures._base.TimeoutError 错误来自何处。
假设您同时在浏览器中打开了 1000 个网址。我敢打赌,您会注意到其中许多在 10 秒后未加载。这不是错误,这是您机器资源的限制。
您正在执行的并行请求更多 -> 每个请求的网络容量更少,每个请求的 CPU 时间更少,每个请求的 RAM 更少 -> 每个请求在它之前未准备就绪的可能性更高超时。
如果您看到 1000 个连接有很多超时,请减少连接(并可能增加超时)。基于 aiohttp
documentation 使用不同的 ClientSession
实例也可能有帮助:
Unless you are connecting to a large, unknown number of different
servers over the lifetime of your application, it is suggested you use
a single session for the lifetime of your application
我遇到了同样的问题,查看 ClientOSError
的详细信息,您可能会看到 Too many open files
,如果是这样,您需要增加 OS' s 文件描述符的数量。
无论哪种方式,如果您打印整个异常,而不仅仅是它们的类型,您将获得更多信息。
我正在尝试从数百万个不同的站点获取状态代码,我正在使用 asyncio 和 aiohttp,我 运行 下面的代码具有不同数量的连接(但请求超时相同)但是得到非常不同的结果,特别是以下异常的数量要多得多。
'concurrent.futures._base.TimeoutError'
密码
import pandas as pd
import asyncio
import aiohttp
out = []
CONNECTIONS = 1000
TIMEOUT = 10
async def fetch(url, session, loop):
try:
async with session.get(url,timeout=TIMEOUT) as response:
res = response.status
out.append(res)
return res
except Exception as e:
_exception = 'Error: '+str(type(e))
out.append(_exception)
return _exception
async def bound_fetch(sem, url, session, loop):
async with sem:
await fetch(url, session, loop)
async def run(urls, loop):
tasks = []
sem = asyncio.Semaphore(value=CONNECTIONS,loop=loop)
_connector = aiohttp.TCPConnector(limit=CONNECTIONS, loop=loop)
async with aiohttp.ClientSession(connector=_connector,loop=loop) as session:
for url in urls:
task = asyncio.ensure_future(bound_fetch(sem, url, session, loop))
tasks.append(task)
responses = await asyncio.gather(*tasks,return_exceptions=True)
return responses
## BEGIN ##
tlds = open('data/sample_1k.txt').read().splitlines()
urls = ['http://{}'.format(x) for x in tlds[1:]]
loop = asyncio.get_event_loop()
future = asyncio.ensure_future(run(urls,loop))
ans = loop.run_until_complete(future)
print(str(pd.Series(out).value_counts()))
结果
CONNECTIONS=1000
CONNECTIONS=100
这是一个错误吗?这些站点确实以状态代码和 运行 顺序响应,或者在连接较低的情况下没有超时错误,那么为什么会发生这种情况?当您更改连接数时,其他异常似乎很稳定。 ClientOSErrors 来自实际超时或响应的站点,老实说并不知道 concurrent.futures._base.TimeoutError 错误来自何处。
假设您同时在浏览器中打开了 1000 个网址。我敢打赌,您会注意到其中许多在 10 秒后未加载。这不是错误,这是您机器资源的限制。
您正在执行的并行请求更多 -> 每个请求的网络容量更少,每个请求的 CPU 时间更少,每个请求的 RAM 更少 -> 每个请求在它之前未准备就绪的可能性更高超时。
如果您看到 1000 个连接有很多超时,请减少连接(并可能增加超时)。基于 aiohttp
documentation 使用不同的 ClientSession
实例也可能有帮助:
Unless you are connecting to a large, unknown number of different servers over the lifetime of your application, it is suggested you use a single session for the lifetime of your application
我遇到了同样的问题,查看 ClientOSError
的详细信息,您可能会看到 Too many open files
,如果是这样,您需要增加 OS' s 文件描述符的数量。
无论哪种方式,如果您打印整个异常,而不仅仅是它们的类型,您将获得更多信息。