在芹菜中,我想将远程工作者的两个任务链接在一起。有人可以告诉我如何在send_task中指定它吗?或者还有其他方法来调用远程任务吗?
BR
答案 0 :(得分:3)
最简单的方法是使用'签名'功能:
from celery import signature
chain = signature(
'app_name.task_1',
kwargs={..},
queue='this_queue'
)
chain |= signature(
'app_name2.task2',
kwargs={..},
queue='another_queue'
)
chain.apply_async()
答案 1 :(得分:2)
我试图做同样的事情。我无法找到任何内置功能来完全按名称生成任务,但添加此类工具并不困难:
from celery import Task as BaseTask
class Task(BaseTask):
def __init__(self, name, *args, **kwargs):
super(BaseTask, self).__init__(*args, **kwargs)
self.name = name
通过这门课程,您可以执行以下操作:
(
Task('worker.hello').s('world') |
Task('messaging.email-results').s(email_address='user@company.com')
)()
或者,或者:
app.send_task(
'worker.hello', ['world'],
chain=[
Task('messaging.email-results').s(email_address='user@company.com')
]
)
修改强>
忽视上面,我已经意识到这样做的正确方法是使用Signature
类(如下面的@Chrismit所述):
from celery import Signature
(
Signature('worker.hello', args=['world']) |
Signature('messaging.email-results', kwargs={'email_address':'user@company.org'})
)()
或者,或者:
from celery import Signature
app.send_task(
'worker.hello', ['world'],
chain=[
Signature('messaging.email-results', kwargs={'email_address': 'user@company.com'})
]
)
一个重要的注意事项:链中的第一个任务之后的任何任务实际上都没有安排,直到一个工人在它之前处理任务(这是有道理的,因为我们不知道输入用于以后的任务,直到上一个任务运行)。 后续任务安排在工作人员的代码库中。因此,您需要确保满足以下条件之一:
task_routes
,以便将后续任务放在适当的队列中(例如,在我的示例中,应该知道以messaging.*
开头的任务应该在'messaging'
队列)您在创建链时已将正确的queue
编码到每个Signature
类中。 Celery已经有了一个工具来从任务名称派生一个队列名称,该名称可以倾斜:
def get_queue_name(task_name):
return app.amqp.router.route({}, task_name)['queue'].name
(
Signature('worker.hello', args=['world']) |
Signature(
'messaging.email-results',
kwargs={'email_address':'user@company.org'},
queue=get_queue_name('messaging.email-results') # If typing the task name twice annoys you, you could subclass Signature to do this automatically
)
)()
(我认为这是最干净的解决方案,因为它允许工人彼此不了解)
task_routes
,并且任务的签名中没有指定queue
,那么Celery将在工作人员中安排该任务default_queue
。除非自定义,即'celery'
。我强烈建议这样做,因为它不是非常明确,并且不允许进行大量队列管理,但仍然是一种选择。答案 2 :(得分:0)
我是这样做的: 诀窍是你必须从你的任务名称中创建新的签名。
app.send_task("{0}.{1}".format(app_name,task),args, link = [app.signature("{0}.{1}".format(app_name,task),next_args)])
答案 3 :(得分:0)
出于某种原因,这种签名方法对我不起作用。它虽然成功创建了签名对象:
signature("some_remote_task", ...)
我的celery版本是4.4,“some_remote_task”定义如下:
celery_app.conf.CELERY_ROUTES = {
"some_remote_task": {
"queue": "remote_queue",
"routing_key": "key",
}
}
然后,由于某种原因,我意识到签名中的 _app=None
。像这样通过后,它起作用了:
signature("some_remote_task", app=celery_app, ...)
答案 4 :(得分:-4)
你可以使用芹菜canvas objects。
from celery import chain
my_chain = chain(task1.s((arg1, arg2)), task2.s((arg3, arg4))
result = my_chain.apply_async()