目前,我在Azure实例上使用Job Scheduler设置了定期任务。这些是在固定时间触发API(Django)端点。
我想让这些时间变得动态(这不适用于此解决方案)。计划是直接从Django发起这些任务。计划时间将存储在我的数据库(MySQL)中并被检索以创建计划作业。更改这些值后,调度程序也应相应更改。
在查看Celery后,似乎使用periodic tasks crontab schedules可以正常工作。 使用此功能,是否可以根据我的数据库中的值设置我的预定时间?
看起来我也需要一个Redis实例。 由于我只使用Celery进行定期任务,它仍然是正确的方法吗?
答案 0 :(得分:3)
Cron被认为可以定期运行任务,因为它具有日常,每小时,每15分钟的简单配置选项...
添加cron作业并不是配置动态任务以在具体日期运行的好方法(或datetime )
还有另一个库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)
我正在使用Django
,Celery
,RabbitMQ
和postgreSQL
。
我正在做你想做的事。
PIP:celery
和flower
您需要一个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),您可以直接更改您的设置(重新加载celery
和celery 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次尝试。
您可以查看flower
是否执行了任务(带回溯):
我每天执行的任务超过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()
您可以拥有任意数量的线程,但要注意并发问题。