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_TZ
Django 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
-
夸格
关键字参数(
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数据库中,并提供一个方便的管理界面来在运行时管理定期任务。
要安装和使用此扩展:
-
使用pip安装软件包:
$ pip install django-celery-beat
-
将
django_celery_beat
模块添加到INSTALLED_APPS
Django项目中settings.py
:INSTALLED_APPS = ( ..., 'django_celery_beat', )
请注意,模块名称中没有短划线,只有下划线。
-
应用Django数据库迁移,以便创建必要的表:
$ python manage.py migrate
-
使用调度程序启动celery beat服务
django_celery_beat.schedulers:DatabaseScheduler
:$ celery -A proj beat -l info --scheduler django_celery_beat.schedulers:DatabaseScheduler
注意:您也可以
beat_scheduler
直接将其添加为设置。 -
访问Django-Admin界面以设置一些定期任务。