cronlike循环任务调度器设计

2024-05-15 14:15:09 发布

您现在位置:Python中文网/ 问答频道 /正文

假设您要安排定期任务,例如:

  • 每周三上午10点发邮件
  • 在每个月的第一天创建摘要

每100k个用户都可以在这个应用程序中决定他们想要做什么。在

你要确保计划的项目运行,即使它们最初被错过了-例如,由于某些原因,电子邮件没有在星期三上午10点发送,它应该在下一个检查间隔发送,比如星期三上午11点。在

你会怎么设计的?在

如果您使用cron每隔x分钟触发一次调度应用程序,那么实现决定在每个时间点运行什么的部分的好方法是什么?在

我见过的类似cron的实现比较了所有指定项的当前时间和触发器时间,但我也希望处理丢失的项。在

我觉得有一个比我正在做的更聪明的设计,所以请给我一些启发。在


Tags: 项目方法用户应用程序间隔电子邮件时间原因
3条回答

基本上有两种设计。在

定期运行并将当前时间与调度规范进行比较(即“现在是否运行?”),并执行符合条件的。在

另一种技术采用当前的调度规范,并找到下一次该项应该触发的时间。然后,它将当前时间与“下一次”小于“当前时间”的所有项目进行比较,并激发这些项目。然后,当一个项目完成时,它将被重新安排到新的“下一次”。在

第一种技术不能处理“遗漏”的项目,第二种技术只能处理那些先前计划好的项目。在

具体来说,你有一个时间表,每小时运行一次,在一个小时的顶部。在

比如说,下午1点,2点,3点,4点。在

下午1:30,run任务关闭,不执行任何进程。下午3点20分才开始。在

使用第一种技术,调度程序将启动1pm任务,但不会启动2pm和3pm任务,因为当这些时间过去时,它没有运行。下一个工作是下午4点的工作,下午4点。在

使用第二种技术,调度程序将在下午1点启动任务,并在下午2点调度下一个任务。由于系统关闭,下午2点的任务没有运行,下午3点的任务也没有运行。但是,当系统在3:20重新启动时,它发现它“错过”了下午2点的任务,并在3:20启动了它,然后将它重新安排在下午4点。在

每一种技术都有它的起起落落。有了第一种技巧,你就会错过工作。有了第二种技术,你仍然可以错过工作,但它可以“赶上”(在一定程度上),但它也可能“在错误的时间”运行一个作业(也许它应该在最快的时间运行是有原因的)。在

第二种技术的好处是,如果在执行作业结束时重新调度,则不必担心级联作业问题。在

假设你有一个每分钟都在运行的作业。有了第一种技术,工作每分钟都会被解雇。但是,通常情况下,如果作业没有在一分钟内完成,那么您可能会有两个作业正在运行(一个在进程后期,另一个正在启动)。如果作业不是设计为同时运行多次,则这可能是一个问题。而且它会加剧(如果真的有问题,10分钟后你有10份工作相互争斗)。在

使用第二种技术,如果您在作业结束时安排,那么如果作业刚好运行了一分钟,那么您将“跳过”一分钟并启动下一分钟,而不是自行运行。因此,您可以为每分钟安排一个作业,实际运行时间为下午1:01、下午1:03、下午1:05等等

这取决于你的工作设计,这两种可能是“好”或“坏”。这里没有正确的答案。在

最后,与实现第二种技术相比,实现第一种技术真的非常简单。与推导cron字符串下一个有效的时间相比,确定cron字符串(例如)是否与给定时间匹配的代码非常简单。我知道,我有几百行代码来证明这一点。它不漂亮。在

如果您想跳过设计并开始使用,请看一下芹菜http://celeryproject.org/。调度程序叫做celerybeat。在

编辑: 也相关:How to send 100,000 emails weekly?

使用带有Quartz scheduler的支持Java进程是一个可能的解决方案。我相信石英应该能很好地达到这个水平。看这个相关的问题:"How to scale the Quartz Scheduler"。。。在

如果您仔细看一下Quartz文档,我想您会发现您对触发和错过执行的担忧得到了干净的处理,并提供了一些合适的策略供您选择。在可伸缩性方面,我相信您可以将作业存储在JDBC备份存储中。在

出局了,因为发问者特别想讨论设计。。。 <罢工> 如果在询问“taskschedulers for Python”这个问题之前,先对StackOverflow搜索进行了框架设置,那么您会发现这个问题:"An enterprise scheduler for python..."。我强烈建议寻找一个现有的实现,而不是尝试像这样的NIH开发,尽管在另一个答案中有很多关于如何做到这一点的观察。考虑到您所声明的可伸缩性目标,您正在咬掉一个相当具有挑战性的任务,并且您应该在从零开始着手研究一个像这个主题这样高度开发的主题之前消除所有的其他选项。考虑的一个可能的方法是通过Jython来适应广受好评的Quartz,并确定您的用例是否可以在该上下文中以最少的方式处理Java世界(大概不是您的首选)。

相关问题 更多 >