• django使用celery进行耗时任务的优化


    # 原创,转载请留言联系

    在用django做项目的时候,做到注册模块时,需要发送短信验证码。本来简简单单的做好了,后来优化的时候发现,发送短信验证码的时候需要一点时间,在这个时间之内程序是阻塞的,用户体验太不好了。往往都是点击获取验证码后,过了几秒钟之后才显示发送成功。所以想到了用celery异步任务队列优化一下。

    celery原理详解:https://www.cnblogs.com/chichung/p/9957763.html

    通过celery可以把发短信验证码的这部分交给其他进程来做,视图继续往下执行,那么当用户点击发送验证码的时候,就能马上显示发送成功了。

    还是先看一下大体流程图:

    • 步骤:

    1.安装celery

    pip install celery

    2.创建celery存放文件件

    一般来用,celery会独立放在项目文件下。

    创建文件夹如下:

    celery_tasks/
    ├── __init__.py
    ├── main.py    # 创建celery应用的地方
    └── sms
        ├── __init__.py
        └── tasks.py    # 任务函数存放的地方,注意,tasks这个名字是固定的,不能改,如果改的话worker找不到!

    3.创建celery应用

    在main.py上:

    from celery import Celery
    
    # 第一个参数,是应用名,可以随便写
    # 第二个参数,是中间人broker(用来保存任务)的储存地方,保存在本机的redis的15号库
    celery_app = Celery("meiduo",broker="redis://127.0.0.1:6379/15")

    4.创建celery任务

    @celery.task  # 装饰器表示把这个函数标记为celery的任务函数
    def send_sms(mobile,sms_codes):
        # 下面是实现短信验证码发送的逻辑
        result = CCP().send_template_sms(mobile, [sms_codes, constants.SMS_CODE_REDIS_EXPIRES // 60],
                                         constants.SEND_SMS_TEMPLATE_ID)

    5.设置django配置文件的路径。

    在main.py上:

    # 设置django配置文件的路径(需要在创建celery应用之前设置),设置了配置文件,celery才知道django的导包路径是怎么样的!
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "meiduo_mall.settings.dev")
    
    
    # 第一个参数,是应用名,可以随便写
    # 第二个参数,是中间人broker(用来保存任务)的储存地方,保存在本机的redis的15号库
    celery_app = Celery("meiduo",broker="redis://127.0.0.1:6379/15")

    6.指定用celery执行的任务函数的位置

    # 设置django配置文件的路径(需要在创建celery应用之前设置),设置了配置文件,celery才知道django的导包路径是怎么样的!
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "meiduo_mall.settings.dev")
    
    
    # 第一个参数,是应用名,可以随便写
    # 第二个参数,是中间人broker(用来保存任务)的储存地方,保存在本机的redis的15号库
    celery_app = Celery("meiduo",broker="redis://127.0.0.1:6379/15")
    
    # 指定任务函数的文件夹位置,表示从哪些位置找到任务函数。
    # 查找的方法是,找到sms文件夹,然后就会自动去找tasks.py。这就是为什么task.py不能乱起名的原因。然后找到task.py里面有celery应用装饰的函数。
    celery_app.autodiscover_tasks(['celery_tasks.sms'])

    7.启动worker进程

    celery -A celery应用所在py文件 worker -l info
        例: celery -A celery_tasks.main worker -l info

        服务器启动后能够看到如下任务,worker进程才能正常工作处理任务
        [tasks]
          . celery_tasks.sms.tasks.send_sms_code

    8.通过装饰器name参数自定义任务名(可选)

    @celery_app.task(name='send_sms_code')
        def send_sms_code(mobile, sms_code):
            ...
            
        自定义完后,启动celery工作进程在输出信息中可以看到如下任务名
        [tasks]
          . send_sms_code

    9.发送任务:  调用delay方法发送异步任务

    在视图可以调用任务函数进行发送任务了,任务会储存在中间人broker,woker空闲时就会取出并执行。

    class SmsCodesView(APIView):
        def get(self,request,mobile):
           ...
            # 发送验证码
            send_sms.delay(mobile,sms_codes)
    
           ...

    10.worker执行任务

    示例:

    [2017-01-22 xxxx: INFO/ForkPoolWorker-2] Task         
    celery_tasks.sms.tasks.send_sms_code[2f4dc753-3cd5-4eaa-994a-d944c45a857c]
    succeeded in 3.2456164589966647s: None

    • 拓展

    1.中间人broker是怎么存储任务的?

    使用json存储:保存了任务函数标识,任务函数名,调用参数等

    2.如果任务函数有返回值,应该怎么取?

    (1)首先,需要有一个地方存储任务函数的返回值。这里选择redis的14号库。

    修改main.py

    celery_app = Celery('meiduo',broker='redis://127.0.0.1:6379/15',backend='redis://127.0.0.1:6379/14')

    这时候,worker执行完任务函数后,会把任务函数的返回值存储在redis上。

    (2)怎么把返回值取出来用呢?

    假设发送短信这个任务函数有返回值,如果是0就是发送成功,是-1就是发送失败。

    result = send_sms.delay(mobile,sms_codes)

    应该怎么拿到result的值呢?

    其实,当worker执行完之后,result.ready()的值是True。未执行完是False。

    当执行会之后(result.ready=True),可以用get方法取出返回值。

    result.get()

     (3)怎么把配置文件独立在一个文件里面呢?

    1. 在celery_tasks包下创建配置文件 config.py, 并定义配置如下
        broker_url ='redis://127.0.0.1:6379/15'
        backend_url='redis://127.0.0.1:6379/14'
        
    2. 加载配置文件
        celery_app = Celery('meiduo')  # 把配置都放到了config.py文件
        celery_app.config_from_object('celery_tasks.config')

  • 相关阅读:
    Tiny_4412的NFS挂载
    tiny4412学习一:编译uboot,体验裸机
    开通博客,记录历程,开启新的征程
    mysql 多表联合做运算(求俩点的距离)
    golang gin框架使用图形验证码
    js rgb和16进制相互转换
    [转载] Centos7的安装、Docker1.12.3的安装,以及Docker Swarm集群的简单实例
    openstack golang sdk使用
    sendcloud golang 发送短信 示例代码
    Harbor配置https,并安装内容信任插件(notary)
  • 原文地址:https://www.cnblogs.com/chichung/p/9960643.html
Copyright © 2020-2023  润新知