zoukankan      html  css  js  c++  java
  • celery在django中的使用

    曾经有一个叫django-celery的模块,大家都用它来做django的异步任务。后来因为它对django、celery还有django-celery的版本要求太高了
    ,稍有不对就用不了,而且至今那个django-celery模块已经很长时间没更新过了,所以大家就都单独使用celery了。但在django中使用需要注意几点也是我遇见的几个坑,后面会讲到。

    1.安装celery

    pip install celery

    2.celery简介

      Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery

      celery有以下优点:

    1. 简单:一单熟悉了celery的工作流程后,配置和使用还是比较简单的
    2. 高可用:当任务执行失败或执行过程中发生连接中断,celery 会自动尝试重新执行任务
    3. 快速:一个单进程的celery每分钟可处理上百万个任务
    4. 灵活: 几乎celery的各个组件都可以被扩展及自定制

      celery组成结构

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

      

      工作流程图 

       

    3.celery的使用

      因为celery本身不提供消息服务,所以需要配置第三方消息中间件,如redis,RebbitMq,若不配置,默认用的RebbitMq
      安装RebbitMq
        https://docs.celeryproject.org/en/latest/getting-started/brokers/rabbitmq.html#id3
      安装reids
        https://www.runoob.com/redis/redis-install.html
      在本篇中使用redis

      1.目录结构

      假设项目名为Demo,app名为app01

        Demo
          Demo
            __init__.py
            settings.py
            celery.py
            ...
          app01
            views.py
            task.py
            ...

      2.settings中配置

    BROKER_TRANSPORT_OPTIONS = {'visibility_timeout': 43200}  # 设置超时时间,一定要设置
    BACKEND='redis://127.0.0.1:6379/3' BROKER='redis://127.0.0.1:6379/4'
    CELERY_TIMEZONE='Asia/Shanghai'
    CELERY_ENABLE_UTC=True

      3.__init__.py中配置

    from __future__ import absolute_import
    from .celery import app as celery_app

      4. celery_task可以放在app中也可以放在app外,根据项目配置。celery.py中需要做配置

    import os
    from celery import Celery
    from NP.settings import BACKEND,BROKER
    from django.conf import settings
    from celery.schedules import crontab
    from datetime import timedelta
    
    # set the default Django settings module for the 'celery' program.
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "NP.settings")
    
    # 若不配置backend和broker,则默认使用rebbitmq作为消息中间件
    app = Celery('app01',backend=BACKEND,broker=BROKER)
    
    # 将celery的settings设置为django的settings,需要配置celery,只需要在settings中配置即可
    app.config_from_object('django.conf:settings')
    
    # 使用这句,则在task中就不需要根据相对路径导入celery对象了,只需要导入shared_task
    app.autodiscover_tasks(lambda :settings.INSTALLED_APPS)
    
    # 设置定时任务
    app.conf.update(
        CELERYBEAT_SCHEDULE={
            'sum-add': {  # 名字随意起
                'task': 'app01.task.add',  # 指定定时任务路径
                'schedule': timedelta(seconds=20),  # 每20执行一次
                'args': (5, 6)
            },
            'send_email': {
                'task': 'app01.task.email',
                'schedule': crontab(hour='18',minute='45'),  # 每天18点45分执行
                'args':(1,2)
            }
        }
    )

      5.task中写任务处理逻辑

      一般来说,一个app中只需要写一个task文件就可以了,异步、定时、延时任务都可配置

    from celery import shared_task
    
    @shared_task
    def add_user(data):
        ...
        return '用户添加成功!'
    
    @shared_task
    def email(data):
        ...
        return '邮件发送成功!'

      6.views中触发任务

    from task import add_user,emial
    from datetime import datetime
    
    class userViewset():
      def post(request):
        ret = add_user.delay(request.data)  # 触发异步任务
    
    class EmailViewset():
      def post(request):
           ctime = datetime.now()  # 当前时间
           utc_time = datetime.utcfromtimestamp(ctime.timestamp())  # 转成本地时间
           time_delta = timedelta(seconds=30)  # 设置延时30s
           task_time = utc_time + time_delta  # 设定时间点为30s后
           ret = add_user.apply_async(args=(request.data,), eta=task_time)  # 触发延时任务

    需要注意的几点:
      1.delay()方法只能传递可被Json序列化的数据,也就是说不能传递对象。如果传了不可序列化的数据则会报错:
        kombu.exceptions.EncodeError: Object of type *args is not JSON serializable

      2.如果配置完成后,执行定时任务时,发现只要添加hour就会无法在指定时间触发任务,则是时区问题

        解决方法:在settings中配置

    CELERY_TIMEZONE='Asia/Shanghai'
    CELERY_ENABLE_UTC=True
  • 相关阅读:
    玩转spring boot——结合JPA事务
    玩转spring boot——结合AngularJs和JDBC
    玩转spring boot——结合jQuery和AngularJs
    028_Mac急救箱快捷键
    006_身体部位名词
    005_Philippines之行准备
    027_MacOs上如何将多页word打印到一个页面上
    026_PPT知识汇总
    025_Excel知识汇总
    024_Word知识汇总
  • 原文地址:https://www.cnblogs.com/gyk1030/p/11688359.html
Copyright © 2011-2022 走看看