zoukankan      html  css  js  c++  java
  • Django+Celery学习笔记4——django+celery+redis周期任务Crontabs设置

      引言

      前面已经讲过定时任务实例,使用的是基于intervals模式的周期任务。这只能满足一部分需求,如果是你想明天早上8点准时执行一个发送邮件的任务,这个时候需要设置一个未来的定时任务,Crontab模式就派上用场。

      参数

      默认参数:

    crontab(minute='*', hour='*', day_of_week='*', day_of_month='*', month_of_year='*')
    

      这些参数可以设置表达式,表达稍微复杂的设置。默认值都是"*"星号,代表任意时刻。即crontab()相当与:含义是每天、每小时、每分钟执行一次任务。这说法太反人类语言习惯,简单说就是每1分钟执行一次任务。

       Crontab语法用五个段来定义时间,具体含义:

    *     *   *   *    *  command to be executed
    -     -    -    -    -
    |     |     |     |     |
    |     |     |     |     +----- day of week (0 - 6) (Sunday=0)
    |     |     |     +------- month (1 - 12)
    |     |     +--------- day of month (1 - 31)
    |     +----------- hour (0 - 23)
    +------------- min (0 - 59)
    
    #所有的值都必须在相应的范围之内,否则视为无效。在填值区域内可以是*也可以是以”,”分隔的一组值。值可以是一个数据也可以是用连接符连起来的两个数(表示范围)。
    #星号(*):代表所有可能的值,例如month字段如果是星号,则表示在满足其它字段的制约条件后每月都执行该命令操作。
    #逗号(,):可以用逗号隔开的值指定一个列表范围,例如,“1,2,5,7,8,9”
    #中杠(-):可以用整数之间的中杠表示一个整数范围,例如“2-6”表示“2,3,4,5,6”
    #正斜线(/):可以用正斜线指定时间的间隔频率,例如“0-23/2”表示每两小时执行一次。同时正斜线可以和星号一起使用,例如*/10,如果用在minute字段,表示每十分钟执行一次。
    注:日期的格式可以是星期,也可以是一个月中的天。假如两个都有值,则在这两个时间都会执行。
    

      具体如下:

    #实例1:每1分钟执行一次command
    * * * * * command
    
    #实例2:每小时的第3和第15分钟执行
    3,15 * * * * command
    
    #实例3:在上午8点到11点的第3和第15分钟执行
    3,15 8-11 * * * command
    
    #实例4:每隔两天的上午8点到11点的第3和第15分钟执行
    3,15 8-11 */2 * * command
    
    #实例5:每个星期一的上午8点到11点的第3和第15分钟执行
    3,15 8-11 * * 1 command
    
    #实例6:每晚的21:30重启smb 
    30 21 * * * /etc/init.d/smb restart
    
    #实例7:每月1、10、22日的4 : 45重启smb 
    45 4 1,10,22 * * /etc/init.d/smb restart
    
    #实例8:每周六、周日的1 : 10重启smb
    10 1 * * 6,0 /etc/init.d/smb restart
    
    #实例9:每天18 : 00至23 : 00之间每隔30分钟重启smb 
    0,30 18-23 * * * /etc/init.d/smb restart
    
    #实例10:每星期六的晚上11 : 00 pm重启smb 
    0 23 * * 6 /etc/init.d/smb restart
    
    #实例11:每一小时重启smb 
    * */1 * * * /etc/init.d/smb restart
    
    #实例12:晚上11点到早上7点之间,每隔一小时重启smb 
    * 23-7/1 * * * /etc/init.d/smb restart
    
    #实例13:每月的4号与每周一到周三的11点重启smb 
    0 11 4 * mon-wed /etc/init.d/smb restart
    
    #实例14:一月一号的4点重启smb 
    0 4 1 jan * /etc/init.d/smb restart
    
    #实例15:每小时执行/etc/cron.hourly目录内的脚本
    01   *   *   *   *     root run-parts /etc/cron.hourly
    
    #注:run-parts这个参数了,如果去掉这个参数的话,后面就可以写要运行的某个脚本名,而不是目录名了
    更多实例戳这里
    

      具体某个值:

    上面提到这些参数的取值范围。我们可以直接设置某个值。例如:
    crontab(minute=15)
    即每小时的15分时刻执行一次任务。直接指定某个时刻。以此类推可以设置每天0点0分时刻执行任务的设置如下:
    crontab(minute=0, hour=0)
    当然,也可以设置多个值。例如0分和30分执行一次任务:
    crontab(minute='0,30')
    这里使用字符串,用逗号隔开数值。这里的逗号是表示多个表达式or逻辑关系。
    

      设置范围:

    设置范围也是设置多个值,例如指定9点到12点每个小时的每分钟执行任务。
    crontab(minute='*', hour='9-12')
    这里*号是默认值,可以省略如下:
    crontab(hour='9-12')
    上面提到逗号是or逻辑关系。拓展一下,指定9点到12点和20点中每分钟执行任务:
    crontab(hour='9-12,20')
    

      设置间隔步长:

    假如我要设置1、3、5、7、9、11月份每天每分钟执行任务,按照上面的做法可以设置如下:
    crontab(day_of_month='1,3,5,7,9,11')
    
    观察数据可以发现,都是间隔2的步长。需要设置的数字比较少,若数字比较多显得很麻烦。例如我想每间隔2分钟就执行一次任务,要写30个数字想想就觉得很麻烦。crontab表达式还提供了间隔的处理,例如:
    crontab(minute='*/2')
    
    #每2个小时中每分钟执行1次任务
    crontab(hour='*/2')
    
    #每3个小时的0分时刻执行1次任务
    #即[0,3,6,9,12,15,18,21]点0分
    crontab(minute=0, hour='*/3')
    
    #每3个小时或8点到12点的0分时刻执行1次任务
    #即[0,3,6,9,12,15,18,21]+[8,9,10,11,12]点0分
    crontab(minute=0, hour='*/3,8-12')
    
    #每个季度的第1个月中,每天每分钟执行1次任务
    #月份范围是1-12,每3个月为[1,4,7,10]
    crontab(month_of_year='*/3')
    
    #每月偶数天数的0点0分时刻执行1次任务
    crontab(minute=0, hour=0, day_of_month='2-31/2')
    
    #每年5月11号的0点0分时刻执行1次任务
    crontab(0, 0, day_of_month='11', month_of_year='5')
    

      场景实例

      上面简单介绍了crontab的设置,具体设置请以下面为准。

      再次确认环境,这个很重要!!!

    amqp==2.6.1
    celery==4.3.0
    Django==2.2.2
    django-celery-beat==1.5.0
    django-celery-results==1.1.2
    django-timezone-field==3.1
    eventlet==0.29.1
    kombu==4.6.11
    PyMySQL==0.9.3
    python-crontab==2.5.1
    pytz==2020.1
    redis==3.2.1
    vine==1.3.0
    

      环境不匹配,你将寸步难行。

      接下来配置几个主要的文件,setting.py文件配置如下:

    LANGUAGE_CODE = 'zh-hans'
    # 简体中文界面
    
    # TIME_ZONE = 'Asia/Shanghai'
    # 亚洲/上海时区
    
    USE_I18N = True
    
    USE_L10N = True
    
    USE_TZ = False
    # 不使用国际标准时间
    
    TIME_ZONE ='UTC'
    # TIME_ZONE = 'Asia/Shanghai'
    
    
    # 设置 django-celery-beat 真正使用的时区
    CELERY_TIMEZONE = TIME_ZONE
    
    CELERY_ENABLE_UTC = True
    # 是否启动时区设置
    
    # 使用亚洲/上海时区
    # CELERY_TIMEZONE = 'Asia/Shanghai'
    
    # 解决时区问题 使用 timezone naive 模式,不存储时区信息,只存储经过时区转换后的时间
    DJANGO_CELERY_BEAT_TZ_AWARE = False
    
    # 使用0号数据库
    CELERY_BROKER_URL = 'redis://127.0.0.1:6379/0'
    # redis://:password@hostname:port/db_number
    # CELERY_BROKER_URL = 'redis://:Abcdef@123456@192.168.1.102:6379/0'
    
    
    
    # 每个 worker 最多执行3个任务就会被销毁,可防止内存泄露
    CELERYD_MAX_TASKS_PER_CHILD = 3
    
    # 使用redis作为中间件  定时任务调度器
    CELERY_BROKER_TRANSPORT = 'redis'
    
    # 自定义调度类,使用Django的ORM
    CELERY_BEAT_SCHEDULER = 'django_celery_beat.schedulers:DatabaseScheduler'
    
    # 使用 database 作为结果存储
    CELERY_RESULT_BACKEND = 'django-db'
    # 任务结果,使用Django的ORM
    
    
    
    
    # celery 内容等消息的格式设置
    if os.name != "nt":
        # Mac and Centos
        # worker 启动命令:celery -A djangocelerydemo worker -l info
        CELERY_ACCEPT_CONTENT = ['application/json', ]
        CELERY_TASK_SERIALIZER = 'json'
        CELERY_RESULT_SERIALIZER = 'json'
    else:
        # windows
        # pip install eventlet
        # worker 启动命令:celery -A djangocelerydemo worker -l info -P eventlet
        CELERY_ACCEPT_CONTENT = ['pickle', ]
        CELERY_TASK_SERIALIZER = 'pickle'
        CELERY_RESULT_SERIALIZER = 'pickle'
    
    
    # CELERY_ACCEPT_CONTENT = ['application/json']
    # # 设置任务接收的序列化类型
    # CELERY_TASK_SERIALIZER = 'pickle'
    # # 设置任务序列化方式
    # CELERY_RESULT_SERIALIZER = 'pickle'
    # # 设置结果序列化方式
    #
    # CELERY_ACCEPT_CONTENT = ['pickle', 'json']
    # # 设置任务接收的序列化类型
    

      celery.py文件配置如下:

    from __future__ import absolute_import, unicode_literals
    import os
    
    from celery import Celery, platforms
    from django.utils.datetime_safe import datetime
    
    # 获取当前文件夹名,即为该 Django 的项目名
    project_name = os.path.split(os.path.abspath('.'))[-1]
    project_settings = '%s.settings' % project_name
    print(project_settings)
    
    # 设置默认celery命令行的环境变量
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djangocelerydemo.settings')
    
    
    # 实例化 Celery,项目名称
    app = Celery('djangocelerydemo')
    
    # 解决时区问题
    app.now = datetime.now
    
    # 使用 django 的 settings 文件配置 celery
    app.config_from_object('django.conf:settings', namespace='CELERY')
    
    # 从所有app应用中加载任务模块tasks.py
    app.autodiscover_tasks()
    
    # 解决celery不能root用户启动的问题
    platforms.C_FORCE_ROOT = True
    
    # 任务过期时间
    # CELERY_TASK_RESULT_EXPIRES = 60 * 60 * 24
    # 有些情况下可以防止死锁
    CELERYD_FORCE_EXECV = True
    

      项目下__init__.py文件的配置如下:

    # 引入celery实例对象
    from __future__ import absolute_import, unicode_literals
    from djangocelerydemo.celery import app as celery_app
    
    __all__ = ('celery_app',)
    
    
    import pymysql
    pymysql.install_as_MySQLdb()
    

      定时任务跟上篇文章一致如:

    # Create your tasks here
    from __future__ import absolute_import, unicode_literals
    
    from djangocelerydemo.celery import app
    
    @app.task
    def plan_task_1():
        print("任务_1已运行!")
        return {"任务_1:success"}
    
    
    @app.task
    def plan_task_2():
        print("任务_2已运行!")
        return  {"任务_2:success"}
    

      项目结构

      上面配置好了,展示一下结构:

       周期任务设置

      先设置一个简单一点的,每隔2分钟执行一次,如:

       配置计划任务,如下:

      执行任务

      1.启动消费者

    celery -A djangocelerydemo worker -l info -P eventlet
    

      2.启动心跳

    celery -A djangocelerydemo  beat -l info
    

      心跳:

     

       消费:

       因为周期任务设置的是每天每2分钟执行一次计划任务,所以这里的时间间隔是2分钟,如图,44-46-48

      总结

      关于周期任务的设置先写到这里,后面还是有很多内容需要深入学习,有兴趣的朋友可以一起,加入学习交流群~

      

  • 相关阅读:
    DNS 域名系统服务
    tomcat
    mysql+redis
    centos7搭建lnmp
    redis安装
    redis 高级应用
    ubuntu,安装、配置和美化(1)
    解决大于5.7版本mysql的分组报错Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column 'userinfo.
    交换机常用命令
    SSH爆破应急响应
  • 原文地址:https://www.cnblogs.com/liudinglong/p/13903441.html
Copyright © 2011-2022 走看看