Celery-周期性任务

Celery(4.4)的当前稳定版本。
官网文档:https://docs.celeryproject.org/en/latest/index.html

周期性任务

简介

celery beat是一个调度程序;它定期启动任务,然后由集群中的可用工作程序节点执行任务。

默认情况下,条目是从beat_schedule设置中获取的,但也可以使用自定义存储,例如将条目存储在SQL数据库中。

您必须确保一次只有一个调度程序针对一个调度程序运行,否则最终将导致重复的任务。使用集中式方法意味着时间表不必同步,并且服务可以在不使用锁的情况下运行。

时区

默认情况下,定期任务计划使用UTC时区,但是您可以使用该timezone 设置更改使用的时区。

时区的示例可以是Europe / London:

timezone = 'Europe/London'

必须使用()直接对其进行配置,或者如果使用对其进行了设置,则必须将其添加到配置模块中,才能 将该设置添加到您的应用中。有关配置选项的更多信息,请参见配置app.conf.timezone = 'Europe/London'``app.config_from_object

默认的调度程序(将调度程序存储在celerybeat-schedule 文件中)将自动检测到时区已更改,因此将重置调度程序本身,但是其他调度程序可能不那么聪明(例如Django数据库调度程序,请参见下文)。在这种情况下,您必须手动重置计划。

Django用户

Celery建议并与USE_TZDjango 1.4中引入的新设置兼容。

对于Django用户,TIME_ZONE将使用设置中指定的时区,或者您可以使用timezone设置单独为Celery指定自定义时区。

与时区相关的设置更改时,数据库调度程序不会重置,因此您必须手动执行此操作:

$ python manage.py shell
>>> from djcelery.models import PeriodicTask
>>> PeriodicTask.objects.update(last_run_at=None)

Django-Celery仅支持Celery 4.0及更低版本,对于Celery 4.0及更高版本,请执行以下操作:

$ python manage.py shell
>>> from django_celery_beat.models import PeriodicTask
>>> PeriodicTask.objects.update(last_run_at=None)

条目

要定期调用任务,您必须在拍子时间表列表中添加一个条目。

from celery import Celery
from celery.schedules import crontab

app = Celery()

@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
    # Calls test('hello') every 10 seconds.
    sender.add_periodic_task(10.0, test.s('hello'), name='add every 10')

    # Calls test('world') every 30 seconds
    sender.add_periodic_task(30.0, test.s('world'), expires=10)

    # Executes every Monday morning at 7:30 a.m.
    sender.add_periodic_task(
        crontab(hour=7, minute=30, day_of_week=1),
        test.s('Happy Mondays!'),
    )

@app.task
def test(arg):
    print(arg)

on_after_configure处理程序中进行设置意味着使用时,我们不会在模块级别评估应用test.s()。请注意,该消息 on_after_configure是在设置应用程序后发送的,因此在声明应用程序的模块之外的任务(例如在位于的task.py文件中 celery.Celery.autodiscover_tasks())必须使用更高的信号,例如 on_after_finalize

add_periodic_task()功能会将条目添加到beat_schedule幕后的 设置中,并且相同的设置还可用于手动设置定期任务:

示例:每30秒运行task.add任务。

app.conf.beat_schedule = {
    'add-every-30-seconds': {
        'task': 'tasks.add',
        'schedule': 30.0,
        'args': (16, 16)
    },
}
app.conf.timezone = 'UTC'

注意

如果您想知道这些设置应该去哪里,请参阅配置。您可以直接在应用程序上设置这些选项,也可以保留单独的模块进行配置。

如果要对args使用单个项目元组,请不要忘记构造函数是逗号,而不是一对括号。

timedelta对时间表使用a 表示任务将以30秒为间隔发送(第一个任务将在开始芹菜拍打 30秒后发送,然后在最后一次运行之后每30秒发送一次)。

还存在类似Crontab的日程表,请参阅有关Crontab日程表的部分。

cron一样,如果第一个任务在下一个任务之前没有完成,则这些任务可能会重叠。如果这是一个问题,则应该使用锁定策略来确保一次只能运行一个实例(例如, 确保确保一次仅执行一个任务)。

可用字段

  • 任务

    要执行的任务的名称。

  • 时间表

    执行频率。

    这可以是整数,a timedelta或a 的秒数 crontab。您还可以通过扩展的界面来定义自己的自定义计划类型schedule

  • args

    位置参数(listtuple)。

  • 夸格

    关键字参数(dict)。

  • 选项

    执行选项(dict)。

    这可以是apply_async()– exchange,routing_key,expires等支持的任何参数 。

  • 相对的

    如果相对是真的,timedelta时间表是“按时”安排的。这意味着频率会根据的时间舍入到最接近的秒,分钟,小时或天 timedelta

    默认情况下,relative为false,频率不四舍五入,将与开始芹菜拍打的时间有关。

Crontab时间表

如果要对执行任务的时间(例如,一天中的特定时间或一周中的一天)进行更多控制,则可以使用crontab计划类型:

from celery.schedules import crontab

app.conf.beat_schedule = {
    # Executes every Monday morning at 7:30 a.m.
    'add-every-monday-morning': {
        'task': 'tasks.add',
        'schedule': crontab(hour=7, minute=30, day_of_week=1),
        'args': (16, 16),
    },
}

这些Crontab表达式的语法非常灵活。

一些例子:

含义
crontab() 每分钟执行一次。
crontab(minute=0, hour=0) 每天午夜执行。
crontab(minute=0, hour='*/3') 每三个小时执行一次:午夜,3am,6am,9am,中午,3pm,6pm,9pm。
crontab(minute=0,``hour='0,3,6,9,12,15,18,21') 和以前一样。
crontab(minute='*/15') 每15分钟执行一次。
crontab(day_of_week='sunday') 在星期日执行每一分钟(!)。
crontab(minute='*',``hour='*', day_of_week='sun') 和以前一样。
crontab(minute='*/10',``hour='3,17,22', day_of_week='thu,fri') 每十分钟执行一次,但仅在周四或周五的凌晨3-4点,下午5-6点以及晚上10-11点之间执行。
crontab(minute=0, hour='*/2,*/3') 每隔一小时执行一次,每一小时被三整除。这意味着:每小时除外:1 am、5am、7am、11am、1pm、5pm、7pm、11pm
crontab(minute=0, hour='*/5') 执行小时可被5整除。这意味着它在下午3点而不是下午5点被触发(因为3pm等于24小时制时钟值“ 15”,可被5整除)。
crontab(minute=0, hour='*/3,8-17') 每小时执行一次可被3整除的时间,并在办公时间(上午8点至下午5点)每小时执行一次。
crontab(0, 0, day_of_month='2') 在每个月的第二天执行。
crontab(0, 0,``day_of_month='2-30/2') 在每个偶数天执行一次。
crontab(0, 0,``day_of_month='1-7,15-21') 在每月的第一和第三周执行。
crontab(0, 0, day_of_month='11',``month_of_year='5') 每年5月11日执行。
crontab(0, 0,``month_of_year='*/3') 在每个季度的第一个月每天执行一次。

请参阅celery.schedules.crontab以获取更多文档。

太阳能时间表

如果您有应根据日出,日落,黎明或黄昏执行的任务,则可以使用 solar计划类型:

from celery.schedules import solar

app.conf.beat_schedule = {
    # Executes at sunset in Melbourne
    'add-at-melbourne-sunset': {
        'task': 'tasks.add',
        'schedule': solar('sunset', -37.81753, 144.96715),
        'args': (16, 16),
    },
}

参数很简单: solar(event, latitude, longitude)

确保对纬度和经度使用正确的符号:

标志 争论 含义
+ latitude
- latitude
+ longitude
- longitude 西方

可能的事件类型是:

事件 含义
dawn_astronomical 在天空不再完全黑暗的那一刻执行。这是当太阳低于地平线18度时。
dawn_nautical 当有足够的阳光照亮地平线并区分一些物体时执行。正式地,当太阳低于地平线12度时。
dawn_civil 当有足够的光线可辨别物体时执行,以便户外活动可以开始;正式地,当太阳在地平线以下6度时。
sunrise 当早晨早晨太阳的上边缘出现在东部地平线上方时执行。
solar_noon 当当天太阳最高到地平线以上时执行。
sunset 当傍晚太阳的后缘在西方地平线上消失时执行。
dusk_civil 当物体仍然可以区分并且可见一些恒星和行星时,在民航末尾执行。正式地,当太阳低于地平线6度时。
dusk_nautical 当太阳低于地平线12度时执行。物体不再可分辨,并且肉眼不再看到地平线。
dusk_astronomical 在天空完全变暗的那一刻执行;正式地,当太阳低于地平线18度时。

所有太阳事件都是使用UTC计算的,因此不受时区设置的影响。

在极地地区,太阳不一定每天都会升起或落下。调度程序能够处理这些情况(即,sunrise在太阳不升起的一天不会发生事件)。一个例外是solar_noon,正式定义为太阳经过天子午线的那一刻,即使太阳在地平线以下,它也会每天发生。

暮光定义为黎明到日出之间的时间;在日落和黄昏之间。您可以使用上面列表中的适当事件,根据您对暮光的定义(民用,航海或天文),以及是否要在暮光的开始或结束时,根据“暮光”安排事件。 。

请参阅celery.schedules.solar以获取更多文档。

启动调度

要启动celery beat服务:

$ celery -A proj beat

您也可以通过启用workers 选项将beat嵌入到worker中,-B如果您永远不会运行一个以上的worker节点,这很方便,但是它并不常用,因此不建议用于生产环境:

$ celery -A proj worker -B

Beat需要将任务的最后运行时间存储在本地数据库文件(默认情况下命名为celerybeat-schedule)中,因此它需要访问权限才能在当前目录中进行写操作,或者可以为此文件指定一个自定义位置:

$ celery -A proj beat -s /home/celery/var/run/celerybeat-schedule

注意

要守护节拍,请参见守护进程

使用自定义调度类

可以在命令行(--scheduler参数)上指定自定义调度程序类 。

默认调度程序是celery.beat.PersistentScheduler,它仅跟踪本地shelve 数据库文件中的最后运行时间。

还有django-celery-beat扩展,可将日程表存储在Django数据库中,并提供一个方便的管理界面来在运行时管理定期任务。

要安装和使用此扩展:

  1. 使用pip安装软件包:

    $ pip install django-celery-beat
    
  2. django_celery_beat模块添加到INSTALLED_APPSDjango项目中settings.py

    INSTALLED_APPS = (
        ...,
        'django_celery_beat',
    )
    

    请注意,模块名称中没有短划线,只有下划线。

  3. 应用Django数据库迁移,以便创建必要的表:

    $ python manage.py migrate
    
  4. 使用调度程序启动celery beat服务django_celery_beat.schedulers:DatabaseScheduler

    $ celery -A proj beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler
    

    注意:您也可以beat_scheduler直接将其添加为设置。

  5. 访问Django-Admin界面以设置一些定期任务。

posted @ 2020-06-01 22:08  自己有自己的调调、  阅读(1387)  评论(0编辑  收藏  举报