celery 使用
celery 使用
基本情况
- 介绍:Celery是一个简单、灵活且可靠的,处理大量消息的分布式系统,专注于实时处理的异步任务队列,同时也支持任务调度。
- 特点:Celery的架构由三部分组成,消息中间件(message broker),任务执行单元(worker)和任务执行结果存储(task result store)组成
- 消息中间件: Celery本身不提供消息服务,但是可以方便的和第三方提供的消息中间件集成。包括,RabbitMQ, Redis等等
- 任务执行单元:Worker是Celery提供的任务执行的单元,worker并发的运行在分布式的系统节点中。
- 任务结果存储:Task result store用来存储Worker执行的任务的结果,Celery支持以不同方式存储任务的结果,包括AMQP, redis等
- note: Celery还支持不同的并发和序列化的手段
- 并发:Prefork, Eventlet, gevent, threads/single threaded
- 序列化:pickle, json, yaml, msgpack. zlib, bzip2 compression, Cryptographic message signing 等等
使用场景
-
celery是一个强大的 分布式任务队列的异步处理框架,它可以让任务的执行完全脱离主程序,甚至可以被分配到其他主机上运行。我们通常使用它来实现异步任务(async task)和定时任务(crontab)。
-
异步任务:将耗时操作任务提交给Celery去异步执行,比如发送短信/邮件、消息推送、音视频处理等等
-
定时任务:定时执行某件事情,比如每天数据统计
-
优点
-
Simple(简单)
- Celery 使用和维护都非常简单,并且不需要配置文件
-
Highly Available(高可用)
- woker和client会在网络连接丢失或者失败时,自动进行重试。并且有的brokers 也支持“双主”或者“主/从”的方式实现高可用
-
Fast(快速)
- 单个的Celery进程每分钟可以处理百万级的任务,并且只需要毫秒级的往返延迟(使用 RabbitMQ, librabbitmq, 和优化设置时)
-
Flexible(灵活)
- Celery几乎每个部分都可以扩展使用,自定义池实现、序列化、压缩方案、日志记录、调度器、消费者、生产者、broker传输等等。
异步任务
-
安装
pip install Celery
-
异步任务执行文件 celery_task.py
import celery import time backend='redis://:xxx@127.0.0.1:6379/1' # 无密码时,则密码前的:也不需要 broker='redis://:xxx@127.0.0.1:6379/2' cel=celery.Celery('test', backend=backend, broker=broker) @cel.task def send_email(name): print(f"向{name}发送邮件...") time.sleep(5) print(f"向{name}发送邮件完成") return "ok"
-
创建执行任务文件 produce_task.py
from celery_task import send_email result = send_email.delay("yuan") # 函数定义时,加了@cel.task,所以有delay方法 print(result.id) # 该id可作为去redis取结果的依据 result2 = send_email.delay("alex") print(result2.id)
-
查看任务执行结果 result.py
from celery.result import AsyncResult from celery_task import cel async_result=AsyncResult(id="c6ddd5b7-a662-4f0e-93d4-ab69ec2aea5d", app=cel) if async_result.successful(): result = async_result.get() print(result) # result.forget() # 将结果删除 elif async_result.failed(): print('执行失败') elif async_result.status == 'PENDING': print('任务等待中被执行') elif async_result.status == 'RETRY': print('任务异常后正在重试') elif async_result.status == 'STARTED': print('任务已经开始被执行')
-
测过过程:
-
首先在终端中启动celery的worker监听redis,准备随时开始做task
celery -A celery_task worker -l info -P eventlet # note: # 加 -P eventlet # celery_task 不要加.py
-
然后,执行product_task.py脚本,向redis中插入task,则第一步已经在等待task的worker立即开始执行。product_task.py脚本中的任务瞬间执行完毕,并返回id。至此,异步执行完毕。
-
最后,查看redis中的结果。或使用result.py查看task的执行进度。依据是第二步获取的id
-
报错
-
ValueError: not enough values to unpack (expected 3, got 0)
-
原因:win10
-
解决方法
pip install eventlet celery -A <mymodule> worker -l info -P eventlet # 加 -P eventlet
-
-
RecursionError: maximum recursion depth
-
原因:redis 设置了密码
-
解决方法 : 密码前必须加 冒号
backend = 'redis://:xxxxx@127.0.0.1:6379/1' # xxx是密码 密码前必须加: backend = 'redis://127.0.0.1:6379/1' # 无密码
-