Python Celery 异步任务库使用简要指南

引言

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 流程

  1. 新建一个 celery.py 文件,用于设置和实例化APP,在 module , init 中配置

  2. 在 django settings 中,配置 基本的配置项,BROKER_URL , RESULT_BACKEND TASK_SERIALIZER, 序列化

  3. 定义自定义的tasks, 通过官方提供的装饰器,注册任务到 celery 中

  4. 本地调试,可以直接用 celery cmd 命令行,启动worker。

    celery -A path/to/your/celery_app worker -l info

  5. 生产环境,以守护进程方式运行 worker。支持 init.d, supervisord, serviced, 方式比较多。配置参考官方文档

一些注意的地方

  1. 配置参数的前缀,celery 4.0+ 已经改变了参数前缀的命名的方法,并且建议小写命名法。
  2. flower 可以用于监控 worker 状态和 task 执行情况。
  3. Django-celery 可以使用 Django框架的cache 或 DB 做消息代理,但是不建议这么用

最佳实践

  1. 不要使用 DB 作为 broker.
    DB 不是设计用来做消息处理的。几个 worker 并发轮询消费任务有可能存在拖垮 DB

  2. 使用多个队列 (不要仅用一个)。
    建议根据任务优先级,设置多个优先级队列。这样对于高优先级的task 可以不受低优先任务的影响。调整worker 参数可以提高对应的消费速度。

  3. 配置优先级worker。配合优先级队列,这样能够保证高优先级的任务不会被低优先级的任务阻塞

  4. 使用 celery error 机制,task 执行过程中很可能遇到第三方服务或者api 宕机的,或者网络问题,最好的办法就是重试。

  5. 使用 Flower 监控

  6. 只在真正有需要时,才跟踪任务结果
    大部分应用不会关心任务的结果,或者任务的结果可以通过其他方式获得,那么就不要在task中显式返回结果,这样会带来一些无用的存储消耗和副产品。特别对于使用DB 作为 result_backend,增加DB 负担。可以使用CELERY_IGNORE_RESULT = True 来忽略掉结果。因为大部分关系的只是任务的执行状态而已。

  7. 不要传入 DB / ORM 对象给tasks,如 User Model
    建议做法,是传入数据的关键字或者索引,在任务中重新建立DB连接获取最新数据,来做处理。因为传入这么大的对象,会给序列化工作带来很大开销,包含很多不必要的信息。

参考文献

  1. https://denibertovic.com/posts/celery-best-practices/
  2. http://www.celeryproject.org/
  3. http://docs.celeryproject.org/en/latest/index.html