我试图了解如何最好地执行以下操作:
考虑多个分析。每个分析都从多个数据源(REST API)请求数据。在每次分析中,当从数据源收集了所有数据时,将检查数据是否存在一个或多个条件。如果满足这些条件,则会向另一个数据源发出另一个请求。
目标是异步收集所有分析的数据,检查每个分析的条件,要求条件是否满足,然后重复。因此,需要满足以下条件:
我进行了以下演示:
import asyncio
import random
async def get_data(list_of_data_calls):
tasks = []
for l in list_of_data_calls:
tasks.append(asyncio.ensure_future(custom_sleep(l)))
return await asyncio.gather(*tasks)
async def custom_sleep(time):
await asyncio.sleep(time)
return random.randint(0, 100)
async def analysis1_wrapper():
while True:
print("Getting data for analysis 1")
res = await get_data([5, 3])
print("Data collected for analysis 1")
for integer in res:
if integer > 80:
print("Condition analysis 1 met")
else:
print("Condition analysis 1 not met")
await asyncio.sleep(10)
async def analysis2_wrapper():
while True:
print("Getting data for analysis 2")
res = await get_data([5, 3])
print("Data collected for analysis 2")
for integer in res:
if integer > 50:
print("Condition analysis 2 met")
else:
print("Condition analysis 2 not met")
await asyncio.sleep(10)
loop = asyncio.get_event_loop()
tasks = analysis1_wrapper(), analysis2_wrapper()
loop.run_until_complete(asyncio.gather(*tasks))
loop.close()
这将产生以下输出:
Getting data for analysis 2
Getting data for analysis 1
Data collected for analysis 2
Condition analysis 2 not met
Condition analysis 2 not met
Data collected for analysis 1
Condition analysis 1 not met
Condition analysis 1 not met
Getting data for analysis 2
Getting data for analysis 1
Data collected for analysis 2
Condition analysis 2 met
Condition analysis 2 not met
Data collected for analysis 1
Condition analysis 1 not met
Condition analysis 1 not met
Getting data for analysis 2
Getting data for analysis 1
Data collected for analysis 2
Condition analysis 2 not met
Condition analysis 2 not met
Data collected for analysis 1
Condition analysis 1 not met
Condition analysis 1 not met
这似乎可以按我的意愿工作。但是,由于我对asyncio和aiohttp的经验有限,因此我不确定这是否是一个好方法。我希望将来能够在管道中添加步骤,例如如果满足条件,则基于围绕发出的请求的逻辑进行操作。此外,它应该可扩展到许多分析,而不会损失太多速度。
答案 0 :(得分:1)
是的,基本上就是这样。需要考虑的几件事:
尽管您可能有无限数量的并发任务,但是随着并发性的增长,每个任务的响应时间也会增长,吞吐量有时会停止增长甚至下降。因为只有一个主线程可以执行所有操作,所以即使网络响应是在几毫秒前到达的,回调也必须在队列过多时排队。为了平衡这一点,通常需要使用Semaphore来控制最大并发性能。
您的代码未显示,但担心的是条件检查可能会占用大量CPU。在这种情况下,您应该将任务推迟到thread pool(没有GIL问题)或子进程(如果GIL是问题)中,其原因有两个:1.阻止阻塞的主线程损害并发性。 2.更有效地利用多个CPU。
您的当前代码在每次分析中循环休眠10秒。这使得很难正常关闭分析仪,更不用说动态扩展了。理想的模型应该是producer-consumer模式,在该模式中,您可以将具有某种控制权的任务生成到Queue中,然后一堆工作人员从队列中检索任务并同时进行处理。