每位芹菜工人的定期任务

时间:2019-08-04 11:10:42

标签: python celery

我正在寻找一种方法来对每个芹菜工人执行特定类型的任务。确切的用例是一项定期的健康工作,它确保成功完成任务初始化和进度的各种前提条件(将这些指标报告给不同的服务)。例如,确保可以建立与数据库的连接。

我发现远程控制和检查命令可以用于此目的(具有一些固定的调度),但是当AWS SQS用作后端代理时,不支持它们。

关于如何在不为分叉的流程任务增加任何内存占用的情况下实现这一目标的任何想法?也许通过在工作进程中启动另一个线程?

2 个答案:

答案 0 :(得分:1)

为解决此问题,我使用了Celery custom worker bootstep。它在启动时注册一个计划任务,该任务每X秒将运行状况检查任务省略到工作程序执行池中。

此解决方案与后端代理无关,并使用自定义的工作程序执行池。

class WorkerHealthMonitor(bootsteps.StartStopStep):
    requires = {'celery.worker.components:Timer',
                'celery.worker.components:Pool'}

    def __init__(self, worker, **kwargs):
        self.tref = None
        self.interval = 60

    def start(self, worker):
        logger.info("Registering health monitor timer with %d seconds interval", self.interval)
        self.tref = worker.timer.call_repeatedly(
            self.interval, schedule_health_check, (worker,), priority=10,
        )

    def stop(self, worker):
        if self.tref:
            self.tref.cancel()
            self.tref = None


def schedule_health_check(worker):
    worker.pool.apply_async(health_check, callback=health_check_completed)


def health_check(**kwargs):
    logger.info('Running Health Check...')
    return 'I am alive'


def health_check_completed(result):
    logger.info('Health check completed with msg: %s', result)

任务注册:

app = Celery('tasks', broker=BROKER_URL, backend=BACKEND_URL)
app.steps['worker'].add(WorkerHealthMonitor)

答案 1 :(得分:0)

尽管您可以执行此操作(我将在下面进一步说明),但我建议您使用出色的Celery monitoring and management API。例如,status命令(以某种方式进行基本的运行状况检查)就是这样实现的,因此您应该将其用作自己实现的基础。

在我了解“检查/控制API”(即我的称呼)之前,我通过为每个工作人员分配一个唯一的队列名称来实现与您要执行的操作类似的操作。然后,您的“发送任务给所有工作人员”将遍历所有唯一的队列名称(例如worker_1worker_2等),并将任务发送到每个队列。