前文列表前言
在前文中我们提到了 Celery 任务的主体是一个函数,那么我们就可以将 Celery 任务工作流理解为「对批量函数的组织与编排」。这里面具有非常浓厚的函数式编程风格,所以要理解 Celery 工作流,首先需要对「函数签名」、「偏函数」以及「回调函数」有所了解。
本篇所用的示例代码承接前文,其中 taks.py 模块有少量修改。
任务签名 signature
使用 Celery Signature 签名(Subtask 子任务),可生成一个特殊的对象——任务签名。任务签名和函数签名类似,除了包含函数的常规声明信息(形参、返回值)之外,还包含了执行该函数所需要的调用约定和(全部/部分)实参列表。你可以在任意位置直接使用该签名,甚至不需要考虑实参传递的问题(实参可能在生成签名时就已经包含了)。可见,任务签名的特性让任务间的组合、嵌套、调配变得更加简单。
任务签名支持「直接执行」和「Worker 执行」两种方式:
生成任务签名并直接执行
生成任务签名在 Worker 执行
偏函数
偏函数(Partial Function Application,PFA):通过固化原函数形参列表的子集,以此得到拥有着新形参列表的函数就是偏函数。e.g.
从某个角度来看偏函数与默认参数非常类似,但也并不完全。你可以基于原函数得到多个不同的偏函数,而且每个偏函数的形参列表都可以不同,这是默认参数所不能满足的。
Celery 中偏函数的应用。e.g.
回调函数
回调函数是一个通过函数指针(函数名)来调用的函数。如果你把函数指针作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就称之为「回调」。回调函数通常会在满足指定条件时被调用,从而对该条件进行响应。
Celery 回调函数的触发条件就是任务执行的「成功」或「失败」。通过 apply_async 方法的参数来指定回调函数。e.g.
任务执行成功回调:
任务执行失败回调:
如果你不希望从上一个任务的结果中获取回调函数的实参,那么你可以将回调函数设置为 immutable(不可变的):
回调函数还可以与偏函数结合使用,以获得更好的灵活性:
NOTE:需要注意的是,回调函数的结果不会被返回,所以使用 Result.get 只也能获取第一个任务的结果。
Celery 工作流
group 任务组
任务组函数接收一组任务签名列表,返回一个新的任务签名——签名组,调用签名组会并行执行其包含的所有任务签名,并返回所有结果的列表。
(并行执行)
chain 任务链
任务链函数同样接收一组任务签名列表,并返回一个新的任务签名——签名链。调用签名链会并串行执行其所含有的任务签名,每个任务签名的执行结果都会作为第一个实参传递给下一个任务签名,最后只返回一个结果。
(串行执行)
chord 复合任务
复合任务函数生成一个任务签名时,会先执行一个签名组(不支持签名链),等待任务组全部完成后再执行一个回调函数。
签名组依旧是并行执行的,但签名组和回调函数时串行执行的,所以 chord 被称为复合任务函数。
chunks 任务块
任务块函数让你能够将需要处理的大量对象分为分成若干个任务块,如果你有一百万个对象,那么你可以创建 10 个任务块,每个任务块处理十万个对象。有些人可能会担心,分块处理会导致并行性能下降,实际上,由于避免了消息传递的开销,因此反而会大大的提高性能。
map/starmap 任务映射
映射函数,与 Python 函数式编程中的 map 内置函数相似。都是将序列对象中的元素作为实参依次传递给一个特定的函数。map 和 starmap 的区别在于,前者的参数只有一个,后者支持的参数有多个。
如果使用 map 来处理 add 函数会报错,因为 map 只能支持一个参数的传入。
JmilkFan-范桂飓
专注于 Python、云计算与大数据
技术即沟通
下一位 offer 达人,就是你 !!
领取专属 10元无门槛券
私享最新 技术干货