在存储在数据库中的时间运行定期任务

时间:2018-05-11 16:02:28

标签: python django celery django-celery celerybeat

目前,我在Azure实例上使用Job Scheduler设置了定期任务。这些是在固定时间触发API(Django)端点。

我想让这些时间变得动态(这不适用于此解决方案)。计划是直接从Django发起这些任务。计划时间将存储在我的数据库(MySQL)中并被检索以创建计划作业。更改这些值后,调度程序也应相应更改。

在查看Celery后,似乎使用periodic tasks crontab schedules可以正常工作。 使用此功能,是否可以根据我的数据库中的值设置我的预定时间?

看起来我也需要一个Redis实例。 由于我只使用Celery进行定期任务,它仍然是正确的方法吗?

3 个答案:

答案 0 :(得分:3)

Cron被认为可以定期运行任务,因为它具有日常,每小时,每15分钟的简单配置选项...
添加cron作业并不是配置动态任务以在具体日期运行的好方法(或datetime

您可以按照scheduler回答中的说明使用this

还有另一个库apscheduler,但检查最后一个版本是否适用于python3(,如果你使用它

from datetime import date
from apscheduler.scheduler import Scheduler

# Start the scheduler
sched = Scheduler()
sched.start()

# Define the function that is to be executed
def my_job(text):
    print text

# The job will be executed on November 6th, 2009
exec_date = date(2009, 11, 6)

# Store the job in a variable in case we want to cancel it
job = sched.add_date_job(my_job, exec_date, ['hello'])

答案 1 :(得分:1)

我正在使用DjangoCeleryRabbitMQpostgreSQL

我正在做你想做的事。

PIP:celeryflower

您需要一个Celery conf文件(在settings.py文件夹中):

您要添加的内容是beat_schedule

app.conf.beat_schedule = {
    'task-name': {
        'task': 'myapp.tasks.task_name',
        'schedule': crontab(minute=30, hour=5, day_of_week='mon-fri'),
    },
}

这将在您的数据库中添加一个条目以执行task_name(星期一至星期五5:30),您可以直接更改您的设置(重新加载celerycelery beat之后)

我喜欢的是你可以通过安全性轻松添加重试机制:

@app.task(bind=True, max_retries=50)
def task_name(self, entry_pk):
    entry = Entry.objects.get(pk=entry_pk)
    try:
        entry.method()
    except ValueError as e:
        raise self.retry(exc=e, countdown=5 * 60, queue="punctual_queue")

当我的method()加注ValueError我将在5分钟内重新执行此方法,最多50次尝试。

好的部分是你可以访问Django admin中的数据库: enter image description here

您可以查看flower是否执行了任务(带回溯):

enter image description here

我每天执行的任务超过1000个,你需要的是创建队列和工人。

我为此使用了10名工人(为了未来的scalling目的):

celery multi start 10 -A MYAPP -Q:1-3 recurring_queue,punctual_queue -Q:4,5 punctual_queue -Q recurring_queue --pidfile="%n.pid"

启动任务的守护进程:

celery -A MYAPP beat -S django --detach

这对你来说可能有些过分,但他可以为你做更多的事情: - 发送电子邮件异步(如果失败,您可以更正并重新发送电子邮件) - 为用户上传和后处理异步 - 每个花费时间但你不想等待的任务(你可以链接任务,需要完成返回结果并在另一个任务中使用它)

答案 2 :(得分:0)

如果没有外部库,请设置每日cron脚本,从数据库中获取今天的任务,并在此时使用线程运行。

def take_a_background_nap(time_to_send):
    while datetime.datetime.now() < time_to_send:
        time.sleep(60)
    print('finally running')
    return


threadObj = threading.Thread(target=take_a_background_nap, args=[datetime.datetime(2020, 5, 11, 12, 53, 0)],)
threadObj.start()

您可以拥有任意数量的线程,但要注意并发问题。