如何让芹菜任务调用异步任务?

时间:2015-12-02 16:25:27

标签: python asynchronous optimization celery django-celery

我有一个需要运行优化算法的django应用程序。该算法由两部分组成。第一部分是进化算法,该算法调用第二部分的一定数量的任务,即模拟退火算法。 问题是芹菜不允许任务调用异步任务。 我在下面尝试过以下代码:

            sa_list = []
            for cromossomo in self._populacao:
                sa_list.append(simulated_annealing_t.s(cromossomo.to_JSON(), self._NR, self._T, get_mutacao_str(self._mutacao_SA), self._argumentos))

            job = group(sa_list)

            result = job.apply_async()
            resultados = result.get()

此代码是进化算法的一部分,这是芹菜任务。 当我试图运行它时,芹菜显示这条消息:

  

[2015-12-02 16:20:15,970:警告/工人-1] /home/arthur/django-user/local/lib/python2.7/site-packages/celery/result.py:45: RuntimeWarning:永远不要在任务中调用result.get()!   见http://docs.celeryq.org/en/latest/userguide/tasks.html#task-synchronous-subtasks

     

在Celery 3.2中,这将导致异常   提出而不是仅仅是一个警告。

尽管只是一个警告,芹菜似乎充满了任务和锁定。

我搜索了很多解决方案,但没有一个解决方案。

2 个答案:

答案 0 :(得分:1)

解决这个问题的一种方法是建立一个2阶段管道:

def first_task():
    sa_list = []
    for cromossomo in self._populacao:
        sa_list.append(simulated_annealing_t.s(cromossomo.to_JSON(), self._NR, self._T, get_mutacao_str(self._mutacao_SA), self._argumentos))

    job = group(sa_list)

    result = job.apply_async()
    result.save()
    return result.id

然后这样称呼:

from path.to.tasks import app, first_task

result_1 = first_task.apply_async()
result_2_id = result_1.get()
result_2 = app.GroupResult.restore(result_2_id)
resultados = result_2.get()

还有其他方法可以做更多工作 - 您可以使用和弦来收集小组的结果。

答案 1 :(得分:1)

问题不在于celery不允许在您的示例中执行异步任务,而是您将遇到死锁,因此警告:

假设您有一个任务A,它产生了许多子任务B到apply_async()。这些任务中的每一个都由工人执行。问题是,如果任务B的数量大于可用工作量,任务A仍在等待他们的结果(在您的示例中,至少 - 默认情况下不是这样)。当任务A仍在运行时,执行任务B的工作人员将执行另一个任务,他们将被阻止,直到任务A完成。 (我不确切知道为什么,但几周前我就遇到了这个问题。)

这意味着在手动关闭工人之前,芹菜不能执行任何操作。

<强>解决方案

这完全取决于您对任务结果的处理方式。如果你需要它们来执行下一个子任务,你可以通过Linking with callbacks链接它们或者将它硬编码到相应的任务中(这样你就可以调用第一个,调用第二个,依此类推)。

如果您只需要查看它们是否已执行且是否成功,您可以使用flower来监控您的任务。

如果您需要进一步处理所有子任务的输出,我建议将结果写入xml文件:让任务A调用所有任务B,完成任务后,执行处理结果的任务C.也许有更优雅的解决方案,但这肯定会避免陷入僵局。