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


报错
  1. ValueError: not enough values to unpack (expected 3, got 0)
    • 原因:win10

    • 解决方法

      pip install eventlet
      celery -A <mymodule> worker -l info -P eventlet  # 加 -P eventlet
      
  2. RecursionError: maximum recursion depth
    • 原因:redis 设置了密码

    • 解决方法 : 密码前必须加 冒号

      backend = 'redis://:xxxxx@127.0.0.1:6379/1'  # xxx是密码 密码前必须加:
      backend = 'redis://127.0.0.1:6379/1'  # 无密码
      
posted @ 2022-02-25 17:38  疯狂列表推导式  阅读(47)  评论(0编辑  收藏  举报