我在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
该消息将被发送到两个队列,并且它们都不会从另一个队列中窃取该消息。
答案 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