如何复制Django Celery工作者?

时间:2012-07-02 11:11:57

标签: django rabbitmq celery

我在Celery(带有RabbitMQ)中有一个记录器,并希望复制其紧急情况的工作。

# tasks.py
@task
def log(message):
    with open('test.txt', 'a') as f:
        f.write(message)


# views.py
log.delay(message)

如何在不同的计算机上生成2个Celery实例,并在调用时运行log()

这样做是否有意义?

这在RabbitMQ中是可行的。如果您有一个topic-based exchange,很明显可以将一条消息放入两个不同的队列,并独立发送给两个接收者。

sender =>
[message, routing_key=event.logging.log] => [queue A, topic=event.#]     
                                                      => receiver 1
                                         => [queue B, topic=*.logging.*]
                                                      => receiver 2

该消息将被发送到两个队列,并且它们都不会从另一个队列中窃取该消息。

2 个答案:

答案 0 :(得分:1)

尝试在两台不同的机器上启动此任务对我没有意义。至少Celery不能保证任务将在不同的机器上运行 - 它是分配负载的RabbitMQ,如果一个节点的负载少于其他节点 - 运行的两个任务可能会在该机器上执行......

请改用task.retry。如果Celery执行失败,它将重试一项任务。芹菜很聪明,可以理解任务是否失败。如果任务失败,请确保引发一些异常,如果无法成功登录,则不要以静默方式返回。

更新:

可能的工作流程可能是 - 尝试执行任务,如果失败,则在on_retry中更改routing_key,并尝试在可以作为故障转移队列的其他交换/队列中执行任务。

答案 1 :(得分:1)

要做到这一点,您必须将交换配置为主题交换(如您所说):

CELERY_QUEUES = {
   'celery': {
       'exchange': 'celerytopic',
       'exchange_type': 'topic',
       'routing_key': 'celery',
   },
}

然后,您可以使用AMQP api创建备份交换:

 from celery import current_app as celery

 with celery.broker_connection() as conn:
     conn.default_channel.queue_declare(queue='celery.backup', durable=True)
     conn.default_channel.queue_bind(queue='celery.backup',
                                     exchange='celerytopic',
                                     routing_key='celery',
                                     durable=True)

由于您已经有一个名为celery的队列,您可能必须先删除它:

$ camqadm queue.delete celery