Celery中任务的重复执行问题

7
几天后,我的芹菜服务将无限期地重复执行一个任务。这有点难以复现,但根据处理的任务量,每周或更频繁地发生。

我将感激任何关于如何获取有关此问题的更多数据的提示,因为我不知道如何追踪它。当它发生时,重新启动芹菜将暂时解决它。

我有一个运行4个工作进程的芹菜节点(版本3.1.23)。代理和结果后端都在Redis上。我只发布到一个队列,并且我不使用芹菜节拍。

Django's setting.py中的配置是:

BROKER_URL = 'redis://localhost:6380'
CELERY_RESULT_BACKEND = 'redis://localhost:6380'

日志的相关部分:

[2016-05-28 10:37:21,957: INFO/MainProcess] Received task: painel.tasks.indicar_cliente[defc87bc-5dd5-4857-9e45-d2a43aeb2647]
[2016-05-28 11:37:58,005: INFO/MainProcess] Received task: painel.tasks.indicar_cliente[defc87bc-5dd5-4857-9e45-d2a43aeb2647]
[2016-05-28 13:37:59,147: INFO/MainProcess] Received task: painel.tasks.indicar_cliente[defc87bc-5dd5-4857-9e45-d2a43aeb2647]
...
[2016-05-30 09:27:47,136: INFO/MainProcess] Task painel.tasks.indicar_cliente[defc87bc-5dd5-4857-9e45-d2a43aeb2647] succeeded in 53.33468166703824s: None
[2016-05-30 09:43:08,317: INFO/MainProcess] Task painel.tasks.indicar_cliente[defc87bc-5dd5-4857-9e45-d2a43aeb2647] succeeded in 466.0324719119817s: None
[2016-05-30 09:57:25,550: INFO/MainProcess] Task painel.tasks.indicar_cliente[defc87bc-5dd5-4857-9e45-d2a43aeb2647] succeeded in 642.7634702899959s: None

任务是通过用户请求发送的:

tasks.indicar_cliente.delay(indicacao_db.id)

这里是任务源代码Celery服务配置文件
为什么在服务运行一段时间后,任务会被多次接收?我该如何获得一致的行为?

谁在安排任务?是用户触发的吗?还是cron触发的?你正在使用celery beat。只发布到一个队列吗? 请粘贴您的celery配置。 - Mauro Rocco
@MauroRocco 用户请求发送任务(不是按计划安排的,我不使用celery beat)。我只发布到一个队列。我已更新我的问题,包括celery配置和任务源代码。 - rodorgas
你的意思是说,如果你在本地运行并且只安排了一个任务,那么你将会看到3个任务正在执行?因为如果这是由用户触发的,那么每个请求它的用户都会有一个任务被安排。 - Mauro Rocco
@MauroRocco 任务通常会按照所期望的行为进行。然而,在服务运行几天后,任务会被多次接收(在短时间内超过100次)。似乎并不是用户触发了这些任务,因为它们具有相同的任务ID(如果是用户请求新任务,日志将显示不同的ID)。 - rodorgas
你能发布安排任务的代码吗? - Mauro Rocco
@MauroRocco 请注意,任务不是按计划安排的,而是使用“delay()”方法异步执行。发送新任务的代码和处理任务的代码在此处 - rodorgas
3个回答

8
可能有点过时,但我曾经遇到过同样的问题,并使用Redis解决了它。简而言之,Celery等待一段时间来执行任务,如果时间已过期,则重新启动任务。这称为可见性超时。
文档中的说明:
如果任务在可见性超时内未被确认,任务将会被重新发送给另一个工作进程并执行。这会导致ETA/倒计时/重试任务的问题,在这些任务的执行时间超过可见性超时时,事实上如果发生这种情况,它将被再次执行,并在循环中反复执行。因此,您必须增加可见性超时以与您计划使用的最长ETA时间相匹配。请注意,Celery将在工作人员关闭时重新传递消息,因此具有长可见性超时只会延迟在断电或强制终止工作人员事件中“丢失”的任务的重新传递。
选项示例: https://docs.celeryproject.org/en/stable/userguide/configuration.html#broker-transport-options

Details: https://docs.celeryq.dev/en/stable/getting-started/backends-and-brokers/redis.html#id1


1
只是补充一下,使用“acks_late”可能会有一些有趣的互动。基本上,如果将其设置为true,则任务仅在完成时确认。这意味着运行时间较长的任务可能会导致此问题。顺便说一句,感谢您在这里的回答。非常有帮助。 - PirateNinjas

1

通过使用RabbitMQ代理而不是Redis解决。


0

我遇到了这样的问题。提高Celery 可见超时并没有起作用。

事实证明,我还在运行一个Prometheus导出器,它实例化了自己的Celery对象,使用了默认的可见超时时间,因此取消了我在应用程序中设置的更高超时时间。

如果您有多个Celery客户端——无论是用于提交任务、处理任务还是仅观察任务——请确保它们都具有完全相同的配置。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接