我已经用Asyncio制作了两个队列系统。
Responder
获取一个链接列表,要求每个链接都有响应,然后将结果放入队列。 Parser
从队列中获取响应,对其进行解析,然后将其添加到另一个队列中。 Submitter
从队列中获取解析的对象,并将其提交到数据库。
下面的代码显示了我如何创建任务。我为Submitter
和Parser
创建了100个实例。问题似乎是,一旦Submitter
达到100个实例,就是这样-提交队列才开始备份。它基本上停止了工作。什么都没有提交了。 Responder
和Parser
通常会继续运行。
submitter
完成工作后,如何回收它?我不想为列表中的每个链接创建一个responder
。这是我代码不完全理解的部分-for s in submitters:
s.cancel()
这会在完成后 杀死我的实例,还是在完成后 杀死我的实例?
async def bulk_submit(not_submitted: set, **kwargs):
parse_queue = asyncio.Queue()
submit_queue = asyncio.Queue()
headers={"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"}
timeout = aiohttp.ClientTimeout(total=60*60)
async with ClientSession(headers=headers, timeout=timeout) as session:
tasks=[]
i=0
for link in not_submitted:
i+=1
tasks.append(
responder(f'RESPONDER-{i}',url=link, session=session, parse_queue=parse_queue, **kwargs)
)
parsers = [asyncio.create_task(parser(f'PARSER-{n}', parse_queue=parse_queue, submit_queue=submit_queue)) for n in range (100)]
submitters = [asyncio.create_task(submitter(f'SUBMITTER-{n}', submit_queue=submit_queue,)) for n in range (100)]
await asyncio.gather(*tasks)
await parse_queue.join()
await episode_queue.join()
await submit_queue.join()
for s in submitters:
s.cancel()
for p in parsers:
p.cancel()
答案 0 :(得分:0)
问题似乎是,一旦
Submitter
达到100个实例,就这样-提交队列刚刚开始备份。 [...]
submitter
完成工作后,如何回收它?
您还没有向我们展示submitter
的代码,因此很难告诉您如何解决问题,甚至难以精确地解决什么问题。根据您显示的代码,您可能会猜测提交者在处理单个队列项目后只是返回了。您实际上在创建100个并行运行的提交者,但是对队列的访问将它们序列化。当每个人都完成工作时,没有其他人可以耗尽提交队列,工作就停止了。
要解决此问题,您无需回收提交者,只需更改它以保持队列中的项目排队,而不是在获得队列项目后退出。它应该看起来像这样:
async def submitter(name, submit_queue):
while True:
item = await submit_queue.get()
... process the item ...
使用此设置,您无需创建100个并行运行的提交者,一个就足够了。 (除非您实际上想要一定程度的并行性,也就是说,在这种情况下,您可以创建任意数量的并行提交。)
这是我代码不完全理解的部分-
for s in submitters: s.cancel()
这会在完成所有操作后或实例完成其工作后杀死我的实例吗?
我怀疑在您的代码中取消操作是无操作的,因为在您致电submitter
时,您所有的cancel()
协程已完成 (取消已完成的任务是忽略)。
通常的想法是在完成工作并且不再需要闲置的工人之后将其杀死。例如,如果submitter
包含如上所示的无限循环,则取消prevent it将在bulk_submit
返回后永远等待新的队列项(并且永远不会接收它们)。