我正在尝试在芹菜中创造一个和弦,它们在一组中的任务本身就是和弦。所以这个想法是 - 每个单独的子链首先执行,然后这些和弦的结果最终被父任务的回调使用。这是我要做的代码
- tasks.py
import celery
from celery import chord
@celery.task
def add(x, y):
print "add called..."
return x + y
@celery.task
def tsum(numbers):
return sum(numbers)
@celery.task
def gr_add(x):
print "**** gr_add called"
c = chord(add.subtask((i,i)) for i in range(2*x, 2*x+2))
r = c(tsum.subtask())
return r.get(timeout=120)
- 然后我的test-chord-chord.py文件包含
from tasks import add, tsum, gr_add
from celery import chord
c = chord(gr_add.subtask((i,)) for i in range(2))
result = c(tsum.subtask())
print result.get(timeout=5)
但是,这没有按预期执行。我做得对吗?有没有其他方法来实现上述目标?
答案 0 :(得分:1)
我终于能够找出问题所在。虽然不太确定如何解决它。罪魁祸首是调用上面gr_add
的回调,特别是行 - r = c(tsum.subtask())
。这将阻止 - 因此运行此任务的工作人员将阻止。现在,当我只有一个工人 - 上面是一个问题。当我开始多个工作人员(在这种情况下特别是三个 - 因为原始和弦创建两个和弦)并且每个只获取一个任务CELERY_PREFTCH_MULTIPLIER = 1
和CELERY_ACKS_LATE=True
。三名工作人员在队列中完成了任务 - 第一次拾取第一个和弦并且现在被阻止。第二个和弦拾起并且现在被阻挡了。第三个拾取第一个和弦的第一个任务 - 计算,退出 - 解锁。接下来的任务 - 计算/退出 - 解锁。第一个现在没有阻止。拾取第二个和弦的第一个任务 - 计算/退出 - 解锁。拾取的工作者1或3中的一个计算出和弦的第二个子任务,计算,退出。现在所有三个都被禁用,结果按预期计算。一般来说 - 这是一个糟糕的设计 - 我应该做的是'创建另一个子任务 - 获得和弦的结果,如果它们还没有成功,只需在一段时间后重试。这些重试间隔之间的时间将允许工作人员完成单个子任务,然后最终可以调用主调用和弦的回调。
编辑1:最后能够弄清楚如何处理这个问题 - 在外部和弦调用的任务中阻塞是一个坏主意。相反,我所做的是 - 从被调用的任务返回AsyncResult 然后创建一个轮询器任务,轮询结果为SUCCESS或FAILURE。然后在此轮询器任务中计算结果。此任务在特定持续时间后重试。 (这几乎就像unlock_chord任务 - 只是我自己在一个由代码控制的单独任务中完成了这个 - 而不是让芹菜处理它)