我需要运行大约500个并发循环。每个循环将按顺序获取分页的REST端点,直到它到达500个端点中每个端点的最后一页。其中一些循环只有5到10页,所以它会快速完成,但其他循环有100页。
问题在于我需要将此URL提取到顺序阻塞循环中,因为由于API限制,必须按顺序提取每个页面(API将抛出错误如果我获取第7页,则第5页获取)。因此,这里的并行单元是每个循环,而不是每个URL在循环内获取。
在任何地方都没有进行繁重的计算。只需获取一个页面,然后将原始内容放入kafka主题中。除了依赖于许多核心的多进程之外,我对任何建议持开放态度。 AsyncIO,Gevent,多线程......
修改1:
实际问题是,如果我使用 aiohttp 异步获取每个循环内的每个页面,我无法保证在第1页之后将获取第2页。请求将被启动以正确的顺序,但绝对不能保证请求将以正确的顺序到达并在端点处理。
编辑2:
正如user4815162342 aiohttp所指出的那样
谢谢!
答案 0 :(得分:1)
在asyncio中,您可以并行启动与端点一样多的循环,并等待所有循环完成。每个循环将使用aiohttp按顺序获取端点页面。例如:
async def download_loop(session, endpoint):
for i in itertools.count(1):
try:
async with session.get(endpoint, params={'page': str(i)}) as resp:
content = await resp.read()
except aiohttp.ClientResponseError:
break # no more pages
# do something with the response content
async def download(endpoints):
loop = asyncio.get_event_loop()
async with aiohttp.ClientSession() as session:
# Start all loops in parallel and wait for them to finish.
# This will start as many loops as there are endpoints.
await asyncio.wait([download_loop(session, endpoint)
for endpoint in endpoints])
# for testing:
loop = asyncio.get_event_loop()
loop.run_until_complete(download(['http://endpoint1', 'http://endpoint2', ...]))
生产代码可能还会捕获aiohttp.ClientConnectionError
并重新尝试该网址。