Task

task 具有如下特点:

  1. task 可以在任何可调用的地方创建。它有双重角色:

    • 定义了当task被调用时,会发送一个消息。
    • 定义了当worker收到消息时会运行消息对应的函数
  2. 每个task都有一个唯一的名字。因此worker才会找到其对应的函数。

  3. 每个task消息都会保存在queue中,直到收到从worker收来的 acknowledged。如果worker因为某些原因死亡了,那么该task消息会被再投递到其它的worker

  4. task不能保证每个任务的幂等性,因此,默认情况下,woker会先回复 acknowledged,然后再执行。因此在确保task幂等的情况下,可以使用task_late 参数,使worker在执行完task之后在回复 acknowledged。

  5. 在如下情况下,woker将会发送 acknowledged消息,即使子进程已经被杀死:

    • 我们不希望task重新运行,因此通过信号/命令等强制核心杀死task进程
    • 系统管理员故意杀死进程,并且不希望它重新运行
    • task需要过得的内存,可能导致核心OOM杀手
    • task即使被重分发了依旧总是失败,产生高频率的消息循环,导致系统失败。

    如果在上述情况中依旧希望task被重新分发,那么可以使用 task_reject_on_worker_lost进行配置。

基础

创建task

@app.task
def function():
return 123

多层装饰器

多个装饰器要确保 @task 在最上层(最外层)

@app.task
@decorator1
@decorator2
def function(x, y):
return x + y

绑定task

绑定task的意思是,task的第一个参数使 task实例本身。

@app.task
def function(self, x, y):
return self.request.id

自定义Task类

通过 @taskbase 参数指定task实现的Task类

@app.task(base=MyTask)
def function(x, y):
return 123

task名

每个task都有一个唯一的名字。可以通过name 参数来给task命名。

@app.task(name='hh')
def function(x, y):
return x + y

如果没有给定task名字,那么task会自动生成一个名字。自动生成的名字由以下部分组成:

  1. 定义task的模块的名字
  2. @task 装饰的函数的名字
# tasks.py

@app.task
def function(x, y):
return x + y
# view.py
from tasks import function
print(function.name) # tasks.function
导入

关于task的导入有两个建议:

  1. 使用绝对导入
  2. 尽量动源头开始导入

例如:在Django中,有如下配置:INSTALLED_APPS = ['project.myapp']

from project.myapp.tasks import mytask  # 这种写法比较好
mytask.name # 'project.myapp.tasks.mytask'
-------------------------------------------------------
from myapp.tasks import mytask # 这种不好,会导致worker注册表中task名字对应不上
mytask.name # 'myapp.tasks.mytask'

修改自定义名字

如果希望修改task自动生成的名字,可以通过覆盖app.gen_task_name() 来实现。

Request

app.Task.request 包含当前执行的task的相关信息

属性 信息
id task的id
group task的group的id
chord task 属于的chord的id
correlation_id
args 传入task函数的位置参数
kwargs 传入task函数的关键字参数
origin 发送该task的主机的名字
retries task重试次数
is_eager 是否在本地以普通函数的方式在本地执行,不通过worker
eta 任务开始的绝对时间(可能会与countdown,retry冲突)
expires 超时时间(任务超时会被取消)
hostname 执行该task的worker的主机名
delivery_info 字典的方式存储 分发该任务的 exchange 和 routing key 信息
reply-to 发送回复的目的地的队列的名字
called_directly 如果task没有通过worker,而是在本地执行,那么该值为True。
timelimit 一个元组(软,硬)限制task的活动时间
callbacks task被成功执行后执行的函数
errback task执行失败后执行的函数
chain 反转一个task列表,形成一个链,列表的最后一个将会是当前task成功执行后的下一个要执行的task

Retry

app.Task.retry()可以用来重分发task。调用retry的时候,会重新分发一个task message,使用和之前一样的task-id,被发送到相同的queue。重分发也会更改task的状态

@app.task(bind=True)
def function(self, x, y):
try:
1/0
except ZeroDivisionError as e:
raise self.retry(exc=e)

app.Task.retry 会引发一个异常,因此,该函数之后的代码将不会被执行。

如果task配置了max_retries 属性,那么在超过重试次数之后,还会引发当前的异常(在本例中是ZeroDivisionError),但是如果有如下两种情况,就会引发其他的异常:

  • 如果没有配置 exc 参数,那么就会引发 MaxRetriesExceededError
  • 指定引发其他异常,self.retry(exc=IndexError())

countdown

定义一个时间——task再次被执行前等待的时间

@app.task(bind=True, default_retry_delay=30 * 60)  # 等待30分钟,默认值3分钟
def function()
try:
1/0
except ZeroDivisionError as e:
raise self.retry(exc=e, countdown=60) # 等待60秒,将会覆盖default_retry_delay

autoretry_for

自动重试。 根据指定的错误,自动重试

@app.task(autoretry_for=(SomeError,))
def function():
....

retry_kwargs

如果想在 retry() 时传入自定义参数

@app.task(autoretry_for=(SomeError,),retry_kwargs={"max_retries":5})
def functon():
...

以上类似于

@app.task(bind=True)
def function():
try:
...
exception SomeError as e:
raise self.retry(exc=e, max_retries=5)

retry_backoff

指数退避; 在重试的过程中,面对冲突,指数退避,默认会把最大延迟限定在10分钟内

如果使用了该配置,那么Task 的 countdown将会被忽略

@app.task(autoretry_for=(SomeException,), retry_baskoff=True)
def function():
...

此配置既可以为 布尔值, 也可以是 数字

  • 为 布尔值

    各次延迟重试时间依据如下规律长

    \(2^2​\) \(2^1​\) \(2^2​\) \(2^3​\) \(2^4​\) …

  • 为 数字(假设为x)

    各次延迟重试时间依据如下规律增长

    \(x\times 2^0\) \(x\times2^1\) \(x\times 2^2\) \(x\times 2^3\) \(x\times2^4\) ….

retry_backoff_max

自动重试延迟最大时间

如果使用 retry_backoff ,那么可以通过该参数配置延迟重试的最大时间。单位为秒,默认为 60*10

retry_jetter

延迟重试过程中,加入随机抖动。默认为True

如果使用了该配置,那么retry_backoff 计算出的时间被视为最大延迟时间,实际重试时间为 0 到最大重试延迟间的随机数

Task其他配置

name

task 的注册名; 默认为所在model名+函数名

request

包含当前请求的相关信息

max_retries

最大重试次数,默认为 3, 如果设置为 None 那么将一直重试直至成功。

throws

预期错误,一个元组。元组中的错误,会被作为失败存储在后端,worker将不会其作为错误记录。且也不包括追踪回溯信息。

@app.task(throws=(ExpectedError, ))
def function():
...

default_retry_delay

默认的重试延迟时间,单位 intfloat 都行。默认是 60*3

rate_limit

设定该类型task在同一个worker被处理的速率,值为 intfloat, 单位为 /s /m /h

默认设置为设置中的 task_default_rate_limit , 如果没有配置,那么表示没有限速。

time_limit

限定task的执行时间,如果超过该时间task仍未完成,那么执行此task的worker将被杀死,并自动产生一个新的worker

soft_time_limit

软限定,当该时间到达后,会引发一个SoftTimeLimitExceeded 异常。可以被捕获并处理。

ignore_result

不记录task的状态。如果使用该配置,那么将不能使用AsyncResult 检查task状态或者是获取task的返回值

store_errors_even_if_ignored

如果使用该配置,即使配置了 ignore_result 也会存储task执行中的错误。

serializer

序列化,可以是 json pickle yaml 或者是其他的自定义序列化反式

compression

压缩方式,可以是 gzip bzip2 或者其他的自定义压缩方式

backend

后端,用来存储task的状态、结果

acks_late

task被执行完成之后,才会向队列发送 acknowledged

因为不确定任务是否为幂等的,所以,默认是在任务执行前发送 ack

track_started

在task开始执行的时候,在task的状态中增加 started 状态,默认是不记录该状态的。

该配置的全局性配置为 task_track_started

Task状态

Celery持续跟踪任务的状态。这其中既包括执行成功的task的结果,也包括失败task的错误信息

内置的状态如下

  • PENDING

    任务的默认状态(即将执行,或者是 未知的任务)

  • STARTED

    任务开始执行。默认不记录该状态

  • SUCCESS

    任务被成功执行。结果存储在后端中

  • FAUILURE

    任务失败,错误信息存储在后端中

  • RETRY

    task 被重试

  • REVOKED

    task 被取消

自定义task状态

使用 update_state() 更新任务的状态

@app.task(bind=True)
def function(self):
self.update_state(state='CHECKPOINT', meta={'error':1})

Ignore

使worker忽略该task,但该task仍旧会回复 ack 到celery,且该task将从队列中移除

Request 中的处理

after_return

task返回之后调用

on_failure

task失败后调用

on_retry

task retry之后执行

on_success

task成功之后执行

自定义Request类

class MyRequest(Request):
def on_timeout(self, soft, time):
super(MyRequest, self,).on_timeout(soft, time)
...
class MyTask(Task):
Request = MyRequest @app.task(base=MyTask)
def function():
...

celery (二) task的更多相关文章

  1. 异步任务利器Celery(二)在django项目中使用Celery

    Celery 4.0支持django1.8及以上的版本,低于1.8的项目使用Celery 3.1. 一个django项目的组织如下: - proj/ - manage.py - proj/ - __i ...

  2. 分布式任务队列 Celery —— 深入 Task

    目录 目录 前文列表 前言 Task 的实例化 任务的名字 任务的绑定 任务的重试 任务的请求上下文 任务的继承 前文列表 分布式任务队列 Celery 分布式任务队列 Celery -- 详解工作流 ...

  3. [源码解析] 并行分布式任务队列 Celery 之 Task是什么

    [源码解析] 并行分布式任务队列 Celery 之 Task是什么 目录 [源码解析] 并行分布式任务队列 Celery 之 Task是什么 0x00 摘要 0x01 思考出发点 0x02 示例代码 ...

  4. 基于Django+celery二次开发动态配置定时任务 ( 一 )

    需求: 前端时间由于开发新上线一大批系统,上完之后没有配套的报表系统.监控,于是乎开发.测试.产品.运营.业务部.财务等等各个部门就跟那饥渴的饿狼一样需要 各种各样的系统数据满足他们.刚开始一天一个还 ...

  5. 结合Django+celery二次开发定时周期任务

    需求: 前端时间由于开发新上线一大批系统,上完之后没有配套的报表系统.监控,于是乎开发.测试.产品.运营.业务部.财务等等各个部门就跟那饥渴的饿狼一样需要 各种各样的系统数据满足他们.刚开始一天一个还 ...

  6. [python基础] celery beat/task/flower解析

    一.Celery 介绍 Celery 是一个强大的分布式任务队列,它可以让任务的执行完全脱离主程序,甚至可以被分配到其他主机上运行.我们通常使用它来实现异步任务( async task )和定时任务( ...

  7. 基于Django+celery二次开发动态配置定时任务 ( 二)

    一.需求 结合上一篇,使用djcelery模块开发定时任务时,定时任务的参数都保存在djcelery_periodictask表的args.kwargs字段里,并且是json格式.那么,当定时任务多了 ...

  8. celery kill task

    from celery.task.control import revokerevoke(task_id, terminate=True) https://stackoverflow.com/ques ...

  9. spark 源码分析之二十二-- Task的内存管理

    问题的提出 本篇文章将回答如下问题: 1.  spark任务在执行的时候,其内存是如何管理的? 2. 堆内内存的寻址是如何设计的?是如何避免由于JVM的GC的存在引起的内存地址变化的?其内部的内存缓存 ...

  10. Celery 源码解析三: Task 对象的实现

    Task 的实现在 Celery 中你会发现有两处,一处位于 celery/app/task.py,这是第一个:第二个位于 celery/task/base.py 中,这是第二个.他们之间是有关系的, ...

随机推荐

  1. C# 每个字节接受 处理串口数据 的方法

      /// <summary> /// 向串口发送信息,有返回值 /// </summary> /// <param name="serialPort" ...

  2. Https网络安全架构设计

    一.对称加密 对称密钥加密(Symmetric-key algorithm)又称对称加密.私钥加密.共享密钥加密,是密码学中的一类加密算法.这类算法在加密和解密时使用相同的密钥,或是使用两个可以简单地 ...

  3. [转]微软商店 打开就显示无法加载该页面 代码0x80131500?

    在某博客看到的方法,供参考,可以尝试一下,我的也是这么解决的 1.打开“运行”输入 inetcpl.cpl (“WINDOWS”+“R”键,输入 inetcpl.cpl亦可) 2.点开高级往下拉,勾上 ...

  4. security cookie 机制(2)--- 初始化___security_cookie

    在 cookie 检查中,必定先要取出初始的 cookie 值: 0011392E A1 14 70 11 00       mov         eax,dword ptr [___securit ...

  5. python第三方库之PyGraphics

    有一段代码要import media,打开python自带的IDLE,输入: >>>import media 就会提示没有media这个模块! 原来media模块不是系统的标准模块, ...

  6. MPU9250九轴陀螺仪--读接口数据

    1.使用i2c链接到树莓派的scl , sda 接口vcc给3v引脚,gnd接树莓派gnd就ok. 2.要操作mpu必须使用mpu的寄存器实现对参数的设定以及读取,取官方下载资料看了一下,在githu ...

  7. nginx的autoindex,目录浏览,配置和美化,美观的xslt_stylesheet

    nginx的autoindex,目录浏览,配置和美化,美观的xslt_stylesheet Nginx custom autoindex with XSLT 转载注明来源: 本文链接 来自osnosn ...

  8. select、poll、epoll之间的区别总结[转载]

    转载:https://www.cnblogs.com/Anker/p/3265058.html select,poll,epoll都是IO多路复用的机制.I/O多路复用就通过一种机制,可以监视多个描述 ...

  9. php如何和linux进行通讯

    FastCGI原理 FastCGI是一个运用于Http Server和动态脚本语言间通信的接口,多数流行的Http Server都支持FastCGI,包括Apache.Nginx和lighttpd等. ...

  10. golang初识2

    1. 赋值与申明 str := "Hello, WebAssembly" // 简短声明 标准格式: var str string str = "Hello, WebAs ...