• celery


    Celery 官网:http://www.celeryproject.org/

    Celery 官方文档英文版:http://docs.celeryproject.org/en/latest/index.html

    Celery 官方文档中文版:http://docs.jinkan.org/docs/celery/

    Celery是一个简单、灵活且可靠的,处理大量消息的分布式系统

    专注于实时处理的异步任务队列

    同时也支持任务调度

    1 celery架构

    # 1. 消息中间件(message broker)
        Celery本身不提供消息服务,但是可以方便的和第三方提供的消息中间件集成。包括,RabbitMQ, Redis等等
        
    # 2. 任务执行单元(worker)和 
        Worker是Celery提供的任务执行的单元,worker并发的运行在分布式的系统节点中。
    
    # 3. 任务执行结果存储(task result store)组成。
        Task result store用来存储Worker执行的任务的结果,Celery支持以不同方式存储任务的结果,包括AMQP, redis等

     2 使用场景

    异步执行:解决耗时任务,将耗时操作任务提交给Celery去异步执行,比如发送短信/邮件、消息推送、音视频处理等等
    
    延迟执行:解决延迟任务
    
    定时执行:解决周期(周期)任务,比如每天数据统计

    3 两种celery任务结构

    1 如果 Celery对象:Celery(...) 是放在一个模块下的

    1)终端切换到该模块所在文件夹位置:scripts
    2)执行启动worker的命令:celery worker -A 模块名 -l info -P eventlet
        注意: 
        1. windows系统需要eventlet支持: pip insall eventlet
        2. Linux与MacOS直接执行:celery worker -A 模块名 -l info
        3.模块名一定要叫celery.py

    2 如果 Celery对象:Celery(...) 是放在一个包下的

    1)必须在这个包下建一个celery.py的文件,将Celery(...)产生对象的语句放在该文件中
    2)执行启动worker的命令:celery worker -A 包名 -l info -P eventlet
        注意: 
        1. windows系统需要eventlet支持: pip insall eventlet
        2. Linux与MacOS直接执行:celery worker -A 模块名 -l info
        3. 模块名一定要叫celery.py

    4 celery执行异步任务

    1 模块结构

    celery_task/celery_app.py

    from celery import Celery
    
    broker = 'redis://127.0.0.1:6379/1'
    backend = 'redis://127.0.0.1:6379/2'
    
    # include=[被管理的任务文件路径, ]
    app = Celery(__name__, broker=broker, backend=backend, include=('celery_task', ))
    
    # 放在模块下的启动celery命令
    '''
    windows中: 
        celery worker -A 模块名 -l info -P eventlet
    linux中: 
        clery worker -A 模块名 -l info
    
    -A: 表示被执行的模块路径. 如果是相对, 那么就需要cd到该模块下执行.
    -l: 表示展示日志    
    '''

    celery_task/celery_task.py

    from celery_app import app
    
    
    @app.task  # 添加任务
    def add(x, y):
        print('x + y:', x + y)
        return x + y

     celery_task/excute_task.py

    import utils
    from celery_task import add
    
    
    # 往broker中添加一个任务.
    '''
    只要是worker一直是在启动的状态, 一旦往broker中添加了任务. 
    那么这个任务就会立刻被worker执行, 执行的结果存储到backend中
    '''
    task_uuid = add.delay(1, 2)
    # 注意: task_uuid是一个AsyncResult对象. 因此需要str才能保存到reids中
    '''
    redis.exceptions.DataError: Invalid input of type: 'AsyncResult'. Convert to a bytes, string, int or float first.
    '''
    # utils.conn.rpush('task_id', task_uuid)  # 错误
    utils.conn.rpush('task_id', str(task_uuid))

     celery_task/get_result.py

    from celery.result import AsyncResult
    
    import utils
    from celery_task import app
    
    if __name__ == '__main__':
        # 通过指定任务的id, 指定开启任务的worker实例化一个异步对象. 当一有结果就可以.get获取到对应任务的返回结果.
        while True:
            task_id = utils.conn.brpop('task_id')[1]
            import time
            time.sleep(0.5)   # 这里就是没办法知道worker什么时候将当前执行任务的id执行成功.
    
            print('task_id:', task_id, type(task_id))  # task_id: c72c2454-6232-477b-986b-3f896e752088 <class 'str'>
            async_obj = AsyncResult(id=task_id, app=app)
            if async_obj.successful():
                result = async_obj.get()
                print(result)
            elif async_obj.failed():
                print('任务失败')
            elif async_obj.status == 'PENDING':
                print('任务等待中被执行')
            elif async_obj.status == 'RETRY':
                print('任务异常后正在重试')
            elif async_obj.status == 'STARTED':
                print('任务已经开始被执行')

     5 注意事项

    # from scripts.celery_task import task2
    # from scripts.celery_task import task1
    '''
    celery_task作为包, 被命令执行时. 如果不将celery_task作为定级导入, 那么任务的执行将会是未被注册的. 任务将不会被运行的worker获取, 将会抛出异常.
    [2020-07-26 19:40:56,983: ERROR/MainProcess] Received unregistered task of type 'scripts.celery_task.task2.task2'.
    
    
    因此, 为了在项目中能够在任意位置都可以执行任务. 因此celery_task必定要放在项目的根目录下的. 那么无论在任何位置导入, 都是没有问题的. 如下:
        from celery_task.a.b.c.d import xxx
        
        如果不是在项目的根目录下, 你的导入也许是这样的.
        from scripts.celery_task import task
        那么worker将找不到你指定的任务的路径. 
    
    本质: 就是由于采用了django的反射机制,使用celery.py所在的celery_task包必须放置项目的根目录下.
    '''
  • 相关阅读:
    [Golang学习笔记] 06 程序实体3 类型断言和类型转换
    [Golang学习笔记] 05 程序实体2 作用域访问权限和变量重声明
    [Golang学习笔记] 04 程序实体1 变量声明
    [Golang学习笔记] 03 库源码文件
    virgo-tomcat-server的生产环境线上配置与管理
    virgo-tomcat-server最大并发连接数的修改
    linux系统下kvm虚拟机的安装
    关于virgo-tomcat-server-3.6.0.RELEASE配置文件修改说明
    关于在Linux下apache-maven的安装
    H3C系列之三层交换机文件管理
  • 原文地址:https://www.cnblogs.com/xupengjun/p/14254585.html
Copyright © 2020-2023  润新知