celery 是 Python 下最流行的基于分布式消息的异步任务库。也支持定时任务。优点:配置方便,集成快速,文档齐全。比较适合 python web 项目中的异步任务开发需求
主要概念
celery 中涉及的概念主要有这几个:
broker: 消息代理。常用存储或消息中间件充当。比如 RabbitMQ (官方推荐), 或 Redis 等,提供高可用的消息队列服务,连接,协调和解耦生成者和消费者.
worker: 工作进程或者线程,从 broker 获取要执行的任务,执行。 一个 worker 包含多个 child 进程,由 pool 参数指定。最为多个执行单元.
task: 用户定义的任务,注册后,供worker 执行.
app: celery 隔离一个管理单元,配置 worker task broker 等信息.
celery 配置
celery 核心几个配置:
BROKER_URL: 代理url, Redis, RabbitMQ
RESULT_BACKEND: 结果返回地址
TASK_SERIALIZER: 序列化类型,可为 json, packle, xml 等。
worker 配置:
concurrency: 并发数,默认与机器CPU核心相当。
max_tasks_per_child: 最大执行任务数。worker 的 child 进程,每执行一定数量的task 就会被啥掉重启,以回收内存,防止内存泄露。
Django 集成 celery 流程
- 新建一个 celery.py 文件,用于设置和实例化APP,在 module , init 中配置
- 在 django settings 中,配置 基本的配置项,BROKER_URL , RESULT_BACKEND TASK_SERIALIZER, 序列化
-
定义自定义的tasks, 通过官方提供的装饰器,注册任务到 celery 中
-
本地调试,可以直接用 celery cmd 命令行,启动worker。
celery -A path/to/your/celery_app worker -l info
-
生产环境,以守护进程方式运行 worker。支持 init.d, supervisord, serviced, 方式比较多。配置参考官方文档。
一些注意的地方
- 配置参数的前缀,celery 4.0+ 已经改变了参数前缀的命名的方法,并且建议小写命名法。
- flower 可以用于监控 worker 状态和 task 执行情况。
- Django-celery 可以使用 Django框架的cache 或 DB 做消息代理,但是不建议这么用
最佳实践
- 不要使用 DB 作为 broker.
DB 不是设计用来做消息处理的。几个 worker 并发轮询消费任务有可能存在拖垮 DB -
使用多个队列 (不要仅用一个)。
建议根据任务优先级,设置多个优先级队列。这样对于高优先级的task 可以不受低优先任务的影响。调整worker 参数可以提高对应的消费速度。 -
配置优先级worker。配合优先级队列,这样能够保证高优先级的任务不会被低优先级的任务阻塞
- 使用 celery error 机制,task 执行过程中很可能遇到第三方服务或者api 宕机的,或者网络问题,最好的办法就是重试。
- 使用 Flower 监控
- 只在真正有需要时,才跟踪任务结果
大部分应用不会关心任务的结果,或者任务的结果可以通过其他方式获得,那么就不要在task中显式返回结果,这样会带来一些无用的存储消耗和副产品。特别对于使用DB 作为 result_backend,增加DB 负担。可以使用CELERY_IGNORE_RESULT = True 来忽略掉结果。因为大部分关系的只是任务的执行状态而已。 - 不要传入 DB / ORM 对象给tasks,如 User Model
建议做法,是传入数据的关键字或者索引,在任务中重新建立DB连接获取最新数据,来做处理。因为传入这么大的对象,会给序列化工作带来很大开销,包含很多不必要的信息。
- 不要使用 DB 作为 broker.