我应该如何处理重叠批处理的RQ工作者

时间:2014-10-12 19:55:26

标签: python django redis python-rq

我已经开始使用RQ / Redis为我的django网站构建一些长时间运行的作业的异步执行。我希望做以下事情:

  • 我想为模型的每个实例建一个队列。您可以将此模型视为api用户帐户。(不会有很多这些。最多15 - 20)

  • 我将在队列中均匀分配批量任务(10到500之间)。在第一批完成之前,可以添加多个批次。

  • 对于每个批处理,我想为每个没有正在处理的队列启动一个worker,我想以批处理模式运行这些worker,这样一旦他们完成了任务,将关闭。

  • 我意识到我不能在批处理模式下运行它们,然后我会一直在处理/监听所有队列的工作。这个问题是我希望能够动态添加和删除队列,所以如果每个批次启动可用队列,它会更好。

我意识到我在队列中分配任务似乎很奇怪,但原因是同一队列中的每个任务都必须根据我使用的服务进行速率限制/限制(将其视为API速率限制,但每个队列代表不同的帐户)。但就我的目的而言,任务运行的帐户没有区别,所以我不妨在所有帐户中进行并行化。

我面临的问题是,如果我启动一个工作人员并给它一个已经处理过的队列,我现在有两个工作人员在该队列上独立运行,因此我的预期节流率减少了一半。如果没有工作人员在该队列上运行,我怎样才能启动工作人员?我可能会找到一个hacky解决方案,但我更愿意处理它"对"方式,因为我没有太多的队列经验,我想我应该问。

我已经在实现自己的工作类,以便我可以动态控制队列,所以我只需要一种方法来添加逻辑,如果该队列已经被处理,它将不会被赋予新的工作者。我的工人的简单版本在这里:

# custom_worker.py
import sys
from Api.models import *
from rq import Queue, Connection, Worker

# importing the necessary namespace for the tasks to run
from tasks import *

# dynamically getting the queue names in which I am expecting tasks
queues = [user.name for user in ApiUser.objects.all()]

with Connection():

    qs = list(map(Queue, queues)) or [Queue()]

    w = Worker(qs)

    w.work(burst=True)

1 个答案:

答案 0 :(得分:2)

寻找解决方案只是意味着深入研究python-rq的源代码。我可能会考虑改进文档。无论如何,这似乎符合我的需要!

import sys
from Api.models import *
from rq import Queue, Connection, Worker

# importing the necessary namespace for the tasks to run
from tasks import *

# Provide queue names to listen to as arguments to this script,
with Connection():

    current_workers = Worker.all()
    working_queues = [queue.name for worker in current_workers for queue in worker.queues]
    proposed_queues = [user.name for user in ApiUser.objects.all()]
    queues_to_start = [queue for queue in proposed_queues if not queue in working_queues]

    if len(queues_to_start) > 0:
        qs = list(map(Queue, queues_to_start))
        w = Worker(qs)
        w.work(burst=True)
    else:
        print("Nothing to do here.")