首页 > 编程知识 正文

python设置定时运行任务,python程序定时运行

时间:2023-05-05 11:12:22 阅读:13062 作者:3861

按时执行某个任务是非常常见的需要,可以通过简单的crontabl完成。 在我们最近的Django项目中,我们使用Ap计划程序来安排定时任务,并遇到了一些问题。

首先,AP计划程序的定位是一个依赖于APP应用程序的任务调度库,非常轻量级。

thatapschedulerisnotadaemonorserviceitself,nordoesitcomewithanycommandlinetools.itisprimarilymeantttoberuninsideexistingapppppols

Apscheduler按照您的APP应用程序启动,没有持久化,没有命令行操作任务工作,而是在APP应用程序内部执行。 其中一个受挫的问题是,每次运行Django manage.py时都启动它,每次跑migrate时都启动,这很可能是我们的使用方法有问题。 只要是紧凑的项目就可以了,但是如果需要管理和控制任务,就有很多限制。

AP计划程序分布式问题

我们面临的问题是,如果Gunicorn部署Django时出现了四个流程实例,而我们的django APP应用程序中还有四个AP计划程序,则在定时创建任务时,每个任务都会执行四次这个很痛。

我们首先使用了使任务的执行具有幂等性的临时解决方案。 任务是将部分数据拉入MySQL数据库。 那么,在数据库中创建Uniqe索引,而不包括以后重复执行的任务。 这种方法显然会浪费资源,但最终可以确保正确,数据不会重复存储。 缺点是,每个任务都必须考虑同步问题、类似的唯一索引或锁定。

然后还有一个解决方案。 manage.py在运行时使用文件锁定。 这样,无论运行多少个Django,都只有一个AP计划程序。 这样就忽视了这个问题,大家可以污染实际定时任务的逻辑。 但是,该锁定对本地多个Django有效。 分布式部署Django会导致问题再次出现,并且每台计算机上有多个Django中的AP计划程序。 在独立的解决多个Ap计划器的方案中,另一个很灵巧,但有点复杂。 原理是先将APP加载到Gunicorn中,然后再fork进程。 加载APP时打开调度程序线程,而fork时不打开线程。 这样,每个Django都有一个工作器,但只有一个计划器。 具体步骤如下。

如果在Gunicorn启动的命令中附加--preload参数,加载app,然后fork进程,则以下代码在master中只运行一次:

1

2

3

4

rerun_monitor=Scheduler ()

rerun_monitor.start (

rerun _ monitor.add _ interval _ job (job _ to _ be _ run,

seconds=JOB_INTERVAL )

作业存储选择非内存选项。 否则,只有一个工作器在运行(与调度器在同一个Django中),所以可以使用外部jobstore将所有工作器移动到调度器

计划程序选择后台计划程序。 因为BackgroundScheduler实现为在调用start ()时打开要调度的线程。 因此,我们在master进程load app时调用一次,Gunicorn fork出现时不会再调用,所以线程继续存在。

Celery解决方案

由于Celery充当分布式任务队列,因此解决方案相对简单。 也就是说,直接只存在一个scheduler,调度任务并由多个工作器运行。

youhavetoensureonlyasingleschedulerisrunningforascheduleatatime,otherwise you’dendupwithduplicatetasks.usingacentralizeduledated

因为只有一个计划程序,所以周期任务不需要同步也不需要锁定。 缺点是一点。 (部署计划程序的位置必须提供可读写文件,以便将上次执行的任务保存到计划程序中。 此计划程序实际上有一个状态。 )

即使是可用性要求不高、周期性任务实时性要求不高的项目,实际上也足够了。 而且我认为celery并不像crontab那么简陋,应该能实现像重试计划失败一样的机制。

其实,我假设的任务时间表应该有多个调度程序,为某个任务、某个时间生成唯一的token,然后将token排队部署任务。 应该可以解决分散问题,即高可用性和幂等。

剩下的几个方案:

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。