我有不同的Rabbit队列,每个队列都专门用于特殊的订单处理:
# tasks.py
@celery.task
def process_order_for_product_x(order_id):
pass # elided ...
@celery.task
def process_order_for_product_y(order_id):
pass # elided ...
# settings.py
CELERY_QUEUES = {
"black_hole": {
"binding_key": "black_hole",
"queue_arguments": {"x-ha-policy": "all"}
},
"product_x": {
"binding_key": "product_x",
"queue_arguments": {"x-ha-policy": "all"}
},
"product_y": {
"binding_key": "product_y",
"queue_arguments": {"x-ha-policy": "all"}
},
我们制定了一项政策,即通过设置CELERY_DEFAULT_QUEUE = 'black_hole'
来强制执行显式路由,然后永远不会从black_hole
消费。
这些任务中的每一个都可以使用celery的canvas原语,如下所示:
# tasks.py
@celery.task
def process_order_for_product_x(order_id):
# These can run in parallel
stage_1_group = group(do_something.si(order_id),
do_something_else.si(order_id))
# These can run in parallel
another_group = group(do_something_at_end.si(order_id),
do_something_else_at_end.si(order_id))
# These run in a linear sequence
process_task = chain(
stage_1_group,
do_something_dependent_on_stage_1.si(order_id),
another_group)
process_task.apply_async()
假设我希望celery.group
,celery.chord
,celery.chord_unlock
和其他画布任务的特定用途流过相应产品的队列,而不是陷入{{1有没有办法用自定义任务名称或自定义routing_key调用每个特定的画布任务?
由于我不会进入的原因,我宁愿不将所有black_hole
任务发送到一个全能celery.*
队列,这是我在此期间所做的。
答案 0 :(得分:4)
此方法允许您将Celery画布任务路由到回调任务的队列。
如here所述,可以为Celery指定基于类的自定义任务路由器。
让我们关注celery.chord_unlock
任务。其签名定义为here。
def unlock_chord(self, group_id, callback, ...):
第二个位置参数是和弦回调任务的签名。
Celery中的任务签名基本上都是dicts,因此我们有机会访问任务选项,包括任务队列名称。
以下是一个例子:
class CeleryRouter(object):
def route_for_task(self, task, args=None, kwargs=None):
if task == 'celery.chord_unlock':
callback_signature = args[1]
options = callback_signature.get('options')
if options:
queue = options.get('queue')
if queue:
return {'queue': queue}
将其添加到Celery配置:
CELERY_ROUTES = (CeleryRouter(),
答案 1 :(得分:0)
我目前正在我的项目中使用Celery。对于某些场景,我需要任务来链接不同的队列:
chain(get_staff.s(url), save_staff.s(dt, partner_id, url))()
这两个函数声明如下:
@task(queue='celery_gevent')
def get_staff(source_url):
@task # send to default queue
def save_staff(suggests, dt, partner, url):
btw, celery_gevent 由具有 gevent 池的工作人员处理,以发出http请求。
此示例,您可以如何隐式指定队列 。您也可以通过指定其他参数来显式将任务放在不同的队列中,如下所示:
In [1]: add.apply_async([4,5])
Out[1]: <AsyncResult: bda3dedd-c2c4-44db-be8e-6a97e718f8b0>
$ sudo rabbitmqctl list_queues
Listing queues ...
celery 1
...done.
In [2]: add.apply_async([4,5], queue='your_product')
Out[2]: <AsyncResult: 934f6161-298b-468b-9716-3da6fae58fa5>
$ sudo rabbitmqctl list_queues
Listing queues ...
celery 1
your_product 1
...done.
您可以在自定义队列中运行整个画布:
process_task.apply_async(queue='your_queue')
尝试在@task
装饰器中指定queue_name。这应该有所帮助。
链接:
http://docs.celeryproject.org/en/latest/reference/celery.app.task.html
http://docs.celeryproject.org/en/latest/_modules/celery/app/task.html#Task.apply_async