10

正确使用Celery中的revoke来取消任务

 2 years ago
source link: https://note.qidong.name/2021/09/celery-revoke/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

正确使用Celery中的revoke来取消任务

2021-09-04 17:17:55 +08  字数:1295  标签: Python

取消操作

Celery(本文基于5.1.2版本)有两种取消操作。

一是通过Control.revoke

from celery.app.control.Control import revoke

ctrl = Control()
ctrl.revoke(task_id)
# Or terminate
ctrl.revoke(task_id, terminate=True)
ctrl.terminate(task_id)

当然,使用Control最简单的办法是直接利用Celery的app对象:

app.control.revoke(task_id)

二是通过AsyncResult.revoke

from celery.result import AsyncResult

result = AsyncResult(task_id)
result.revoke()
# Or terminate
result.revoke(terminate=True)

二者基本是等价的,只是后者常用于复杂的操作场景,前者只是单纯地取消。 更多关于revoke的内容,可以参考Revoking tasks

以下基于AsyncResult.revoke进行介绍,省略写task_id

取消任务

并非所有任务状态,都可以取消。对于已经结束的任务,取消是无效操作。

PENDINGSTARTEDSUCCESSFAILURERETRYREVOKED

可以被取消的只有:

  • PENDING
  • STARTED
  • RETRY

取消PENDING

这代表Task还在排队中,没有真正运行。只需要使用普通的取消即可。

result.revoke()

它的原理是,发广播通知所有worker,更新revoked列表。 当worker执行到revoked列表中的任务时,会直接跳过。

如果一个任务已经在运行,则以上操作无效。 因此,它只适用于取消未运行任务的场景,业务能容忍、或要求已运行任务自然地执行完毕。

取消STARTED

如果一个任务已经在运行,通常处于STARTED状态。 取消这个任务,意味着中断这个运行过程。

result.revoke(terminate=True)
# Or with signal
import signal
result.revoke(terminate=True, signal=signal.SIGTERM)

要注意的是,terminate=True意味着使用给定的signal,结束任务进程。 这里的signal,可以是signal模块的任意值。 默认的signal=None,即等价于signal=signal.SIGTERM

在结束任务进程时,任务自己是不知道的。 因此,这只适用于粗暴终止的场景。

然而,SIGTERM有时候并没有粗暴到底,会等一会儿,往往不是预期行为。 因此,如果要以终止的方式取消正在运行的任务,也可以使用SIGQUIT

利用SIGUSR1

尽管所有的signal都是可用的,但是有四个是Celery预留的特殊signal,详见Process Signals

Signal 原文 备注 SIGTERM Warm shutdown, wait for tasks to complete. 热停止,默认行为。 SIGQUIT Cold shutdown, terminate ASAP 冷停止。 SIGUSR1 Dump traceback for all active threads. 发一个SoftTimeLimitExceeded异常。 SIGUSR2 Remote debug, see celery.contrib.rdb. 调试专用。

其中,SIGTERM就是默认的Signal,很粗暴;SIGQUIT则比它更粗暴。 至于不在上面的SIGKILLSIGINT等,也不见得好多少。 如果想要让被终止的任务知道自己被终止,目前只能使用SIGUSR1

它会在任务正在执行的位置,抛出一个SoftTimeLimitExceeded。 因此,只需要在最外层用try ... except捕获这个异常,就可以进行一些后处理。 但是,由于它的现象和任务超时是类似的,因此需要自行区分。

结论

对于只取消没有在运行的任务,只需要revoke即可; 对于已经在运行的任务,则需要terminate=True。 默认的signal=signal.SIGTERM,有时结束得不够快,有时过于粗暴,缺少一些后处理。 因此,对不关心其运行情况的业务,也可考虑使用SIGQUIT,甚至SIGKILL。 对于需要做取消前做一些处理的,可以用SIGUSR1


Recommend

  • 7

    Celery+django如何显示任务的执行进度条 Celery单词中文的意思是“芹菜”,也不知道为什么人家喜欢给起个菜名,实际从功能上跟芹菜一点也扯不上关系,非得往上靠难道国外吃芹菜是在后面吃?大家都知道,如果我们在后端执行一个时间比较...

  • 6

    Python中使用Celery和Redis构建任务队列 | blutv您拥有的微服务越多,您就越需要在微服务或计划作业或后台任务之间进行异步消息传递。后台任...

  • 11

    Django动态添加定时任务之django-celery的使用 定时任务和周期任务在我们日常工作中应用广泛,例如定时发布、周期巡检等,通常我们会借助Linux下的Crontab来实现,但如何将这一功能搬进我们自研的运维系统呢?借助django-celery即可轻松完成...

  • 2

    Django配置Celery执行异步任务和定时任务 原生Celery,非djcelery模块,所有演示均基于Django2.0 celery是一个基于python开发的简单、灵活且可靠的分布式任务队列框架,支持使用任务队列的方式在分布式的...

  • 8

    Python Celery 任务执行有时成功有时失败(提示NotRegistered) 原创 tzchao 2022-03-31 11:...

  • 6
    • tomoncle.github.io 2 years ago
    • Cache

    celery分布式任务队列

    celery分布式任务队列 Posted on...

  • 1
    • yinwc.github.io 2 years ago
    • Cache

    基于Celery的后台任务

    Celery简介Celery 是一个异步任务队列/基于分布式消息传递的作业队列,Celery 是一个强大的分布式任务队列,它可以让任务的执行完全脱离主程序,甚至可以被分配到其他主机上运行。通常使用它来实现异步任务(async task)和定时任务(crontab)

  • 2

    以前版本的 Celery 需要一个单独的库(django-celery)才能与 Django 一起工作, 但从 Celery 3.1 开始,情况便不再如此,我们可以直接通过 Celery 库来完成在 Django 中的任务。 安装 Redis 服务端...

  • 7
    • acejoy.com 6 months ago
    • Cache

    排查 Celery 队列的任务问题

    排查 Celery 队列的任务问题 2023/9/26 0 Comments 198 Views 0 Times 近日使用 Celery 队列系统构造服务,遇到队列任务无法执行的问题,经过排查找到原因,记录一下,防止日后忘记。Celery 是一...

  • 2

    Celery多队列解决生产环境下的任务优先级问题 运维自动化系统需要处理大量的周期任务,例如上篇文章

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK