[英]Run multiple Celery tasks using a topic exchange
我正在用 Celery 替换一些本土代码,但很难复制当前的行为。 我想要的行为如下:
user.created
路由键将消息发布到tasks
交换。send_user_activate_email
和check_spam
。 我尝试通过使用ignore_result=True
参数定义user_created
任务以及send_user_activate_email
和check_spam
的任务来send_user_activate_email
check_spam
。
在我的配置中,我添加了以下路由和队列定义。 当消息传递到user_created
队列时,它不会传递到其他两个队列。
理想情况下,消息仅传送到send_user_activate_email
和check_spam
队列。 使用 vanilla RabbitMQ 时,消息被发布到一个交换器,队列可以绑定到该交换器,但 Celery 似乎直接将消息传递到队列。
我将如何在 Celery 中实现上述行为?
CELERY_QUEUES = {
'user_created': {'binding_key':'user.created', 'exchange': 'tasks', 'exchange_type': 'topic'},
'send_user_activate_email': {'binding_key':'user.created', 'exchange': 'tasks', 'exchange_type': 'topic'},
'check_spam': {'binding_key':'user.created', 'exchange': 'tasks', 'exchange_type': 'topic'},
}
CELERY_ROUTES = {
'user_created': {
'queue': 'user_created',
'routing_key': 'user.created',
'exchange': 'tasks',
'exchange_type': 'topic',
},
'send_user_activate_email': {
'queue': 'user_created',
'routing_key': 'user.created',
'exchange': 'tasks',
'exchange_type': 'topic',
},
'check_spam': {
'queue': 'user_created',
'routing_key': 'user.created',
'exchange': 'tasks',
'exchange_type': 'topic',
},
}
听起来您希望单个消息触发/被两个队列使用,但这不是 Celery 的工作方式。 Exchange 会将任务发布到符合条件的队列,但是一旦它被消耗,其他队列就会忽略该消息。 每个要触发的任务都需要一条消息。
Celery 新用户经常会混淆,因为在这个系统中“队列”有两种用途; Queue() 和文档所引用的 Kombu 队列,以及直接保存消息并由工作人员使用的 AMQP 队列。 当我们发布到队列时,我们想到的是 AMQP 的,这是不正确的。 (感谢回答链接如下)。
回到你的问题,如果我理解正确,当 user_created 被消耗时,你希望它产生两个以上的任务; send_user_activate_email 和 check_spam。 此外,这些不应相互依赖; 它们可以在不同的机器上并行运行,不需要知道彼此的状态。
在这种情况下,您希望 user_created “apply_async”这两个新任务并返回。 这可以直接完成,或者您可以使用包含 check_spam 和 send_user_activate_email 的 Celery“组”来实现此目的。 该小组提供了一些不错的速记,并为您的任务提供了一些结构,因此我个人会向您推荐这个方向。
#pseudocode
group(check_spam.s(... checkspam kwargs ...), send_user_activate_email.s(... active email kwargs ...)).apply_async()
此设置将创建四个消息; 一个用于您要执行的每个任务,另外一个用于 Group(),这本身就会产生结果。
在您的情况下,我不确定 Exchange 或 ignore_result 是否必要,但我需要查看任务代码并更多地了解系统才能做出判断。
http://docs.celeryproject.org/en/latest/userguide/canvas.html#groups http://celery.readthedocs.org/en/v2.2.6/userguide/routing.html#exchanges-queues-and-routing -keys 为什么 CELERY_ROUTES 有“队列”和“路由密钥”?
(如果我离开我会删除/删除答案......)
设计和解决问题的简单方法是使用 Celery 工作流程。
但首先,我会更改您的队列定义,为每个任务设置唯一的路由键,并使用“直接”值设置 exchange_type。
根据celery 文档,直接交换通过精确的路由键匹配,因此我们为所有自定义任务和消费者队列设置相同的交换,并像下一个片段一样映射 routing_key(用于任务)和 binding_key(用于队列):
CELERY_QUEUES = {
'user_created': {'binding_key':'user_created', 'exchange': 'tasks', 'exchange_type': 'direct'},
'send_user_activate_email': {'binding_key':'send_user_activate_email', 'exchange': 'tasks', 'exchange_type': 'direct'},
'check_spam': {'binding_key':'check_spam', 'exchange': 'tasks', 'exchange_type': 'direct'},
}
CELERY_ROUTES = {
'user_created': {
'queue': 'user_created',
'routing_key': 'user_created',
'exchange': 'tasks',
'exchange_type': 'direct',
},
'send_user_activate_email': {
'queue': 'send_user_activate_email',
'routing_key': 'send_user_activate_email',
'exchange': 'tasks',
'exchange_type': 'direct',
},
'check_spam': {
'queue': 'check_spam',
'routing_key': 'check_spam',
'exchange': 'tasks',
'exchange_type': 'direct',
},
}
完成此更改后,您需要对可用列表 ( http://docs.celeryproject.org/en/latest/userguide/canvas.html#the-primitives ) 使用正确的工作流程。 阅读您的问题,我认为您需要一个链,因为需要保留顺序。
sequential_tasks = []
sequential_tasks.append(user_created.s(**user_created_kwargs))
sequential_tasks.append(send_user_activate_email.s(**send_user_activate_email_kwargs))
sequential_tasks.append(check_spam.s(**check_spam_kwargs))
#you can add more tasks to the chain
chain(*sequential_tasks)()
Celery 将透明地处理与队列相关的工作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.