文章目录
Celery
相关资料
官方文档: https://docs.celeryproject.org/en/latest/index.html
博客文章:https://www.cnblogs.com/dachenzi/p/8082730.html
https://www.cnblogs.com/ftl1012/p/9457767.html
Celery概述
关于celery的定义,首先来看官方网站:
Celery(芹菜) 是一个简单、灵活且可靠的,处理大量消息的分布式系统,并且提供维护这样一个系统的必需工具。
简单来看,是一个基于python开发的分布式异步消息任务队列,持使用任务队列的方式在分布的机器、进程、线程上执行任务调度。通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery, 举几个实例场景中可用的例子:
- 你想对100台机器执行一条批量命令,可能会花很长时间 ,但你不想让你的程序等着结果返回,而是给你返回 一个任务ID,你过一段时间只需要拿着这个任务id就可以拿到任务执行结果, 在任务执行ing进行时,你可以继续做其它的事情。
- 你想做一个定时任务,比如每天检测一下你们所有客户的资料,如果发现今天 是客户的生日,就给他发个短信祝福 。
Celery 在执行任务时需要通过一个中间人(消息中间件)来接收和发送任务消息,以及存储任务结果,完整的中间人列表请查阅官方网站
PS:任务队列是一种在线程或机器间分发任务的机制。
PS:消息队列的输入是工作的一个单元,称为任务,独立的工作(Worker)进程持续监视队列中是否有需要处理的新任务。
Celery简介
Celery 系统可包含多个职程和中间人,以此获得高可用性和横向扩展能力,其基本架构由三部分组成,消息中间件(message broker),任务执行单元(worker)和任务执行结果存储(task result store)组成。
- 消息中间件,Celery本身不提供消息服务,但是可以方便的和第三方提供的消息中间件集成,一般使用rabbitMQ or Redis,当然其他的还有MySQL以及Mongodb。
- 任务执行单元,Worker是Celery提供的任务执行的单元,worker并发的运行在分布式的系统节点中。
- 任务结果存储,Task result store用来存储Worker执行的任务的结果,Celery支持以不同方式存储任务的结果,包括Redis,MongoDB,Django ORM,AMQP等。
Celery的主要特点:
- 简单:一单熟悉了celery的工作流程后,配置和使用还是比较简单的
- 高可用:当任务执行失败或执行过程中发生连接中断,celery 会自动尝试重新执行任务
- 快速:一个单进程的celery每分钟可处理上百万个任务
- 灵活: 几乎celery的各个组件都可以被扩展及自定制
Celery基本工作流程图
- 用户应用程序讲任务通过celery放入Broker中。
- 多个worker通过Broker获取任务并执行。
- worker执行完成后,会把任务的结果、状态等信息返回到Broker中存储,供用户程序读取。
Celery 用消息通信,通常使用中间人(Broker)在客户端和职程间斡旋。这个过程从客户端向队列添加消息开始,之后中间人把消息派送给职程。
Celery模块的基本使用
官方文档:https://docs.celeryproject.org/en/latest/getting-started/first-steps-with-celery.html
要使用Celery需要先安装celery模块,下面的例子使用Python3进行举例。
# 利用pip3命令安装celery模块
pip3 install celery
# 测试是否成功安装
[root@namenode ~]# python3
Python 3.6.4 (default, Dec 21 2017, 17:26:43)
[GCC 4.4.7 20120313 (Red Hat 4.4.7-16)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import celery # 没有报错表示模块安装正常
>>>
PS:如果你是编译安装的Python3,执行以上步骤后不一定代表正确安装,还需要在命令行下执行celery命令,
如果报错请参考这篇文章:Python3安装Celery模块后执行Celery命令报错
下面的例子使用redis作为消息中间人的角色。
1.创建一个celery application
用来定义任务列表,这里任务文件的名称为tasks.py
from celery import Celery
app = Celery('tasks', broker="redis://127.0.0.1:6379", backend="redis://127.0.0.1:6379")
# task 是当前模块的名称,这个参数是必须的,这样的自动生成
# 中间人的地址
# 结果数据存放地址
@app.task # 使用celery标识一个任务,多个任务都需要使用该装饰器
def add(x, y):
return x + y
其他中间件的用法
# rabbitmq
broker = 'amqp://user:password@ip:5672//'
# redis
broker = 'redis://passwordf@ip:6379/db'
2.运行一个worker
celery -A tasks worker --loglevel=debug
# -A参数表示的是Celery APP的名称,tasks就是APP的名称(应用文件名) 也可使用--app 等价于 -A
# worker表示是一个执行任务角色
# loglevel=info记录日志类型默认是info。
3.发布(调用)任务
from tasks import add
result = add.delay(4, 4)
print('Is task ready: %s' % result.ready())
run_result = result.get(timeout=1)
print('task result: %s' % run_result)
PS:调用任务会返回一个 AsyncResult 实例,可用于检查任务的状态,等待任务完成或获取返回值(如果任务失败,则为异常和回溯)。 但这个功能默认是不开启的,需要设置一个 Celery 的结果后端(配置了backend才会生效)。
PS:通过检查redis的数据也可以查看结果信息
注意事项:这是我个人遇到的一些问题
版本问题 python3.6+ celery4.1.0+ 这个是可以正确使用的搭配
以下报错建议安装eventlet 安装
Celery ValueError: not enough values to unpack (expected 3, got 0)的解决方案
Python3.5 建议使用protobuf3.0.0.beta2
AsyncResult 实例常用方法
通过获取异步执行对象的返回值来获取Asynz cResult实例对象
from tasks import add
result = add.delay(4, 4) # 返回一个result对象
run_result = result.get(timeout=1)
- ready() 方法查看任务是否完成处理