celery 学习笔记 01-介绍

celery 是 python 中的常用的任务队列框架,经常用于异步调用、后台任务等工作。celery 本身以 python 写,但协议可在不同的语言中实现,其它语言也可以用 celery 执行相应的任务。在 web 应用,为提高系统响应速度,发送邮件、数据整理等需要长时间执行的任务,通常以异步任务的方式执行,这时就需要用到像 celery 类的框架。另一种常见的场景是大型系统的分布式处理,为了提升系统性能,各个组件通常以多个实例运行不同主机上,而组件之间的调用就需要用到 celery 这样的框架。使用 celery (或消息队列),有助于降低系统组件之间的耦合,有助于实现灰度发布、实现服务的分布式、实现水平扩展,最终提升系统健壮性和处理性能。

celery (和类似框架)的核心是任务队列。用户发起任务,celery 负责把任务排队和整理,然后交到任务执行器 worker 中。 worker 监视任务队列,获取新任务并执行。在 celery 内部,以消息机制协调各个组件工作,消息需要借助一个中间人 broker 进行,如下 ::

client → celery task → broker → celery worker
↑ ↓
← ← ← ← result backend

client 发起任务时,一般是以异步方式(除非必要的同步 rpc ),获得一个任务的 id 并保存下来,后续可通过 id 到 result backend 中查询任务执行结果。broker 是第三方组件,可使用消息队列( rabbitmq 等)、redis、数据库等,只要能实现消息的存储和分发理论上都能使用。 worker 以线程或进程的形式运行,从 broker 中取任务执行,然后把结果保存到 result backend 。

目前 rabbitmq 的 broker 实现的功能最完备,在开发环境中也可以使用 sqlite 等比较方便的方式,但性能会很差,不能用在生产环境上。

另外需要注意的是,由于不同操作系统的进程模型的差异,celery 会在 windows 上产生一些配置方面的怪异问题。

celery 可直接通过 pip 安装,在 virtualenv 下,直接运行 ::

pip install celery

再安装 broker 所需要的驱动,例如使用 rabbitmq ,则安装 ::

pip install amqp

同时安装好 rabbitmq (建议通过 docker 安装,使用 rabbitmq:management 镜像,可在 15672 端口查看管理控制台)。

然后使用下面的代码示例(摘录来自: Ask Solem. “Celery Manual, Version 3.1“) ::

# hello.py
from celery import Celery app = Celery('hello', broker='amqp://guest:guest@localhost//') @app.task
def hello():
return 'hello world' if __name__ == '__main__':
r = hello.delay()

然后,启动 worker ::

celery -A hello worker --loglevel=info

client 执行任务 ::

python hello.py

app.task 装饰器标记一个函数为 celery 任务,client 用 delay 方法执行时。 delay 调用 apply_async() 进行异步执行, apply_async 还可配置如队列、countdown 等执行选项。 celery 返回一个 AsyncResult 对象,如果 result backend 配置正确,client 可暂时把对象中的任务 id 保存到数据库,后面再通过这个 id 获取异步执行的结果。

上面的简单例子是没有参数的,如果增加参数,如下 ::

# add.py
from celery import Celery app = Celery('add', broker='amqp://guest:guest@localhost//',
backend='db+sqlite:///celery_result.db') @app.task
def add(x, y):
return x+y if __name__ == '__main__':
r = add.delay(1, 2)
print(r.wait())

启动 worker ::

celery -A add worker --l info

调用 ::

python add.py

当任务结果用 amqp 保存时,结果只能取一次, 因此无法在后续调用中查询任务结果。这个例子用 sqlite 保存了任务执行结果,因此 client 可在 r.wait() 查询任务的结果、任务的状态等等很多信息,可把 r.id 保存到数据库,然后未来查询任务的 AsyncResult ::

r2 = app.AsyncResult(r.id)
print(r2.wait())
print(r2.successful())

add.py 中使用了两个参数 x y ,而 celery 需要通过 broker 传递这两个参数,这时需要对数据进行序列化,将 x y 对象转换为无结构的数据,然后 worker 接收到后再把数据还原为 x y 对象。 celery 内置的序列化方法包括 pickle 、 json 等等,如果对象比较复杂,需要自己定义序列化方法。

如果不想立即执行任务,而是把任务传递到其它地方,通过 celery 的 subtask 支持。 subtask 是对 task 的调用参数和执行选项的一个封装,如 ::

add.subtask((2,2), countdown=10)
add.s(2,2)

subtask 或 s 返回的是一个 task 的签名(celery.canvas.Signature),它可实现工作流、偏函数等效果。subtask 支持和 task 同样的调用方法,如 ::

s = add.s(2)    # subtask ,partial
s.delay(2) # 发送消息开始异步执行

在 celery 工作流中组织 subtask 的方式有 group / chain / chord 等等, group 中任务并发执行,chain 中任务顺序执行,chord 中进行回调。而这些组织方式本身也是 subtask ,可嵌套使用 ::

# workflow.py
from celery import Celery, group, chain app = Celery('add', broker='amqp://guest:guest@localhost//',
backend='db+sqlite:///celery_result.db') @app.task
def add(x, y):
return x+y if __name__ == '__main__':
g = group((add.s(i, i) for i in range(10)))
r = g.delay()
print(r.get()) c = chain(add.s(1, 2) | add.s(3))
r2 = c.delay()
print(r2.get())

celery 的任务调用通过网络发送任务的名字和参数,不发送任务代码, worker 收到任务后根据任务名和参数执行相应的代码。因此不同 worker 中的代码版本不一样时,会有不同的处理结果。如果 worker 中不能处理相应的任务名,就会报错。

celery 学习笔记 01-介绍的更多相关文章

  1. C++ GUI Qt4学习笔记01

    C++ GUI Qt4学习笔记01   qtc++signalmakefile文档平台 这一章介绍了如何把基本的C++只是与Qt所提供的功能组合起来创建一些简单的图形用户界面应用程序. 引入两个重要概 ...

  2. 软件测试之loadrunner学习笔记-01事务

    loadrunner学习笔记-01事务<转载至网络> 事务又称为Transaction,事务是一个点为了衡量某个action的性能,需要在开始和结束位置插入一个范围,定义这样一个事务. 作 ...

  3. ASP.NET Core Web开发学习笔记-1介绍篇

    ASP.NET Core Web开发学习笔记-1介绍篇 给大家说声报歉,从2012年个人情感破裂的那一天,本人的51CTO,CnBlogs,Csdn,QQ,Weboo就再也没有更新过.踏实的生活(曾辞 ...

  4. SaToken学习笔记-01

    SaToken学习笔记-01 SaToken版本为1.18 如果有排版方面的错误,请查看:传送门 springboot集成 根据官网步骤maven导入依赖 <dependency> < ...

  5. Redis:学习笔记-01

    Redis:学习笔记-01 该部分内容,参考了 bilibili 上讲解 Redis 中,观看数最多的课程 Redis最新超详细版教程通俗易懂,来自 UP主 遇见狂神说 1. Redis入门 2.1 ...

  6. vue.js 2.0 官方文档学习笔记 —— 01. vue 介绍

    这是我的vue.js 2.0的学习笔记,采取了将官方文档中的代码集中到一个文件的形式.目的是保存下来,方便自己查阅. !官方文档:https://cn.vuejs.org/v2/guide/ 01. ...

  7. PHP 学习笔记 01

    例子: 为什么要学PHP 主观原因: 前段时间在学校处理了毕业的一些事情,回到上海后开始了找工作的旅程.意向工作是WPF开发或者ASP.NET 作为后端的WEB开发. 陆陆续续一直在面试,其中有一家公 ...

  8. xml基础学习笔记01

    注意:刚刚看了网上对于XML中的标签,节点和元素?到底应该怎么表述?起初我也有这个疑惑,现在我的想法是:下面出现node的应称作节点,节点对象.element应称作元素,毕竟这更符合英文的本意.至于标 ...

  9. FPGA-VHDL课堂学习笔记*01

    FPGA-VHDL课堂学习笔记 记录说明:本文档主要记录大学期间,老师FPGA授课课堂笔记. 代码语言:VHDL 编程软件:MAX+plus II FPGA硬件:FLE-843 03月05日  理论课 ...

随机推荐

  1. hdu-acm steps Common Subsequence

    /*这道题是很明显的dp题,状态方程有点不大好想,也许是我刚刚接触dp的缘故吧.dp[i][j]表示字符串s1取前i个字符s2取前j个字符时最大公共子序列的大小,这样的如果s1[i]==s2[j],d ...

  2. shadowColor表示阴影颜色,shadowBlur表示模糊等级

    绘制之前的准备工作: 1.在body中加入canvas标签,设置它的id.width.height,当然也可以动态设置它的宽高. <canvas id="mycanvas" ...

  3. gnuplotx轴的logscale显示

    假设数据是这样子的: gnuplot脚本如下: set terminal postscript eps color enhanced set log x set log y set format x ...

  4. 词频统计(WEB版)

    通过点击浏览按钮输入文件: 点击查询按钮后返回结果: 前台代码: <%@ Page Language="C#" AutoEventWireup="true" ...

  5. [Zz] DX depth buffer

    声明:本文完全翻译自DX SDK Documentation depth buffer,通常被称为z-buffer或者w-buffer,是设备的一个属性,用来存储深度信息,被D3D使用.当D3D渲染一 ...

  6. DS实验题 order

    算法与数据结构 实验题 6.4 order ★实验任务 给出一棵二叉树的中序遍历和每个节点的父节点,求这棵二叉树的先序和后序遍历. ★数据输入 输入第一行为一个正整数n表示二叉树的节点数目,节点编号从 ...

  7. Nginx 笔记与总结(16)nginx 负载均衡

    nginx 反向代理时,如果后端有多台服务器,就可以实现负载均衡. 实现原理:把多台服务器用 upstream 绑定在一起并起一个组名,然后 proxy_pass 指向该组. ngx_http_ups ...

  8. spring mvc返回json字符串数据,只需要返回一个java bean对象就行,只要这个java bean 对象实现了序列化serializeable

    1.spring mvc返回json数据,只需要返回一个java bean对象就行,只要这个java bean 对象实现了序列化serializeable 2. @RequestMapping(val ...

  9. Visual Studio解决方案及项目的配置

    配置解决方案的属性 1.配置解决方案平台,该配置实际上修改的是解决方案目录下的sln(solution)文件. 配置项目的属性 1.配置项目平台及项目的目标平台:项目-右键-属性-生成(竖着第二个选项 ...

  10. MVC validation

    <div class="editor-field"> @Html.TextBoxFor(m => m.DateField) @Html.ValidationMes ...