首页 文章

类似cron的重复任务调度程序设计

提问于
浏览
8

假设您要安排重复性任务,例如:

  • 每周三上午10点发送电子邮件

  • 在每个月的第一天创建摘要

并且您希望在Web应用程序中为合理数量的用户执行此操作 - 即 . 每个用户可以决定他们想要安排的时间 .

并且您希望确保计划的项目运行,即使它们最初是错过的 - 例如 . 由于某种原因,电子邮件没有在星期三上午10点发送,它应该在下一个检查间隔发出,比如周三上午11点 .

你会如何设计?

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

我见过的类似cron的实现将当前时间与所有指定项目的触发时间进行比较,但我也想处理错过的项目 .

我觉得有一个比我正在烹饪的设计更聪明的设计,所以请赐教 .

3 回答

  • 4

    基本上有两种设计 .

    一个人定期运行并将当前时间与调度规范进行比较(即“现在运行吗?”),然后执行符合条件的那些 .

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

    第一种技术无法处理“遗漏”物品,第二种技术只能处理先前预定的物品 .

    特别考虑到您有一个每小时运行一次的计划,在一小时的顶部 .

    所以,比方说,下午1点,下午2点,下午3点,下午4点 .

    下午1:30,运行任务已关闭,未执行任何进程 . 直到下午3:20才开始 .

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

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

    每种技术都有它的起伏 . 使用第一种技术,你会错过工作 . 使用第二种技术你仍然可以错过工作,但它可以“赶上”(到一定程度),但它也可能“在错误的时间”运行工作(也许它应该在一小时内运行原因) .

    第二种技术的好处是,如果您在执行作业的END处重新安排,则不必担心级联作业问题 .

    考虑一下你有一份每分钟都有的工作 . 使用第一种技术,工作每分钟都会被解雇 . 但是,通常情况下,如果作业在一分钟内没有完成,那么您可能有2个作业正在运行(一个在此过程中,另一个在启动时) . 如果作业不是设计为同时运行多次,则可能会出现问题 . 它可能会加剧(如果有一个真正的问题,10分钟后你有10个工作都互相争斗) .

    使用第二种技术,如果你在工作结束时安排,那么如果一项工作恰好在一分钟内运行,那么你将“跳过”一分钟“然后启动下一分钟而不是自己运行所以,你可以安排在每分钟实际运行的工作时间为下午1点01分,下午1点03分,下午1点05分等 .

    根据您的工作设计,这些中的任何一个都可能是“好”或“坏” . 这里没有正确的答案 .

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

  • 2

    如果您想跳过设计并开始使用,请查看芹菜http://celeryproject.org/ . 调度程序称为celerybeat .

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

  • 6

    使用带有Quartz scheduler的后备Java进程可能是一个潜在的解决方案 . 我相信Quartz应该能够很好地扩展到这个水平 . 看到这个相关的SO问题:"How to scale the Quartz Scheduler" ...

    如果您仔细查看Quartz文档,我想您会发现您的疑虑关于触发和错过的执行是干净利落的,并提供了一些合适的政策供选择 . 在可伸缩性方面,我相信您可以将作业存储在JDBC后备存储中 .

    结束了,因为提问者专门寻找设计讨论......如果在根据“Python的任务调度程序”提出问题之前构建了初始的StackOverflow搜索,那么你可以解决这个问题:“企业调度程序蟒蛇...” . 我强烈建议寻找一个现有的实现,而不是尝试NIH开发这样的事情,尽管在另一个答案中你可能会如何做到这一点 . 鉴于您所述的可扩展性目标,您正在寻找一项相当具有挑战性的任务,并且您应该逐步消除所有其他选项,然后再深入研究与此相关的主题 . 一个可能的考虑途径是通过Jython适应备受好评的Quartz,并确定您的用例是否可以在该上下文中处理,而最小化的是Java世界(可能不是您的首选) .

相关问题