要定时或者周期性的执行任务,可以使用linux的crontab。Celery也提供了类似的Periodic Tasks功能。
Celery beat
Celery使用celery beat作为任务调度器,周期性的启动任务。
需要执行的任务默认是在beat_schedule配置选项中设置的。使用django-celery-beat时,也可以使用数据库存储。
需要保证同一时间只有一个任务调度器在运行,否则会重复的执行任务。
Time Zones
既然是任务与时间有关,那么时区设置是很重要的。Celery默认使用UTC时区,要改变默认时区,可以配置:
timezone = Asia/Shanghai'
在django项目中使用celery时,celery也可以使用setting的TIME_ZONE时区设置。
使用默认的任务调度器时,celery会自动识别时区的改动,然后重置任务调度。使用其它任务调度时,需要手动重置。
比如,使用django-celery-beat时:
$ python manage.py shell
>>> from djcelery.models import PeriodicTask
>>> PeriodicTask.objects.update(last_run_at=None)
Entries
要添加周期任务,需要将事务添加到任务调度器中,添加方法有两种。
一种是使用add_periodic_task() 方法:
from __future__ import absolute_import, unicode_literals
from celery.schedules import crontab
from .celery import app
@app.on_after_configure.connect
def setup_periodic_tasks(sender, **kwargs):
# Calls add(1, 2) every 10 seconds.
sender.add_periodic_task(10.0, add.s(1, 2), name='add every 10')
# Calls add(3, 4) every 30 seconds
sender.add_periodic_task(30.0, add.s(3, 4), )
# Executes every Monday morning at 7:30 a.m.
sender.add_periodic_task(
┆ crontab(hour=7, minute=30, day_of_week=1),
┆ add.s(1, 2),
)
@app.task
def add(x, y):
print x + y
return x + y
另一种方法是配置beat_schedule选项:
app.conf.beat_schedule = {
'add-every-30-seconds': {
'task': 'tasks.add',
'schedule': 30.0,
'args': (3, 4)
},
}
可用字段:
task:需要执行的任务名称
schedule:任务执行时间设定,可以是整秒数,一个timedelta对象,或者一个crontab对象,也可以自己实现。
args:一个元组或者列表,位置参数
kwargs:一个字典,关键字参数
options:一个字典,一些额外选项,apply_async()方法可用的参数,exchange, routing_key, expires等
relative:默认false
Crontab
class celery.schedules.crontab(minute=u'*', hour=u'*', day_of_week=u'*', day_of_month=u'*', month_of_year=u'*', **kwargs)
一个表示时间间隔的对象,语法与linux的crontab类似。
minute和hour可以设置为*/15,*/2,分别表示每隔15分钟和每隔2小时。
day_of_week用可以0-6的数字表示,也可以文字表示mon-fri。*/2并不是每2天,而是每半天。
官网一些具体例子:
crontab() 每分钟
crontab(minute=0, hour=0) 每天的0时0分
crontab(minute=0, hour='*/3') 每三小时
crontab(day_of_week='sunday') 周日的每一小时
crontab(minute='*',hour='*', day_of_week='sun') 与上面相同
crontab(minute=0, hour='*/3,8-17') 每三个小时 8时到17时的每小时
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)
event表示日落日出,latitude为纬度,北纬为+,longitude为经度,东经为+。
启动
启动celery beat周期任务命令:
$ celery -A proj beat
然后启动worker节点来处理任务即可。
beat与worker也可以同时启动,但最好只用于测试,适用于只启动一个worker节点的情况:
$ celery -A proj worker -B
beat会在当前目录下建立一个文件celerybeat-schedule来记录任务上次运行的时间,所以要保证celery对当前目录有写入的权限,或者指定文件位置:
$ celery -A proj beat -s /home/celery/var/run/celerybeat-schedule