mehr-it/lara-cron

为Laravel提供的动态、用户可管理的分布式定时任务

2.3.0 2021-11-23 12:47 UTC

README

Latest Version on Packagist Build Status

本包帮助实现用户可管理的分布式定时任务。定时任务存储在数据库表中,当给定的cron表达式匹配时执行。

与其他cron实现不同,此包始终使用队列来调度定时任务。定时任务将定期发送到队列,在它们到期前几分钟,但有一定的延迟,因此任务将在期望的执行时间收到。

这种方法有以下几个优点

  • 短时间内(几分钟)的调度器停机不会导致定时任务丢失
  • 如果错过,定时任务可以追回
  • 定时任务执行可以跨多台机器分布
  • 您可以在多台机器上执行定时任务调度器,无需担心重复的定时任务调度,因为重复预防已经内置

使用方法

创建定时任务非常简单

$cron = new CronExpression('*/15 * * * *', 'Europe/Berlin');

Cron::schedule($cron, $job);

Cron::schedule($cron, $job, 'myJob', 'jobGroup');

要更新现有定时任务,只需再次调用带有相同键参数的schedule()即可。

要删除定时任务,只需调用delete()方法

Cron::delete('myJob');

您还可以列出所有定时任务,可选地按组名过滤

Cron::describeAll();

Cron::describeAll('myGroup'); 	

调用调度器

定时任务调度器将所有即将到期的定时任务调度到队列。默认情况下,它由Laravel的调度器每五分钟调用一次,调度未来10分钟内到期的定时任务。

您可以通过设置以下选项来禁用此行为

// config/cron.php

'dispatch_schedule' => false,

然后您需要手动调用artisan cron:dispatch 600600指定了调度定时任务的周期(以秒为单位)。此值应始终大于这些调度器调用之间的时间间隔。

错过定时任务的追赶

系统会失败。即使是定时任务调度器。或者运行调度器的系统可能会关闭一段时间。因此,您可以为定时任务指定一个追赶超时作为最后一个参数。

Cron::schedule($cron, $job, 'my-job', null, true, 300);

调度器将尝试为在指定时间段内到期但尚未安排的任务进行一些追赶。

DST处理

DST(夏令时)和cron表达式可能非常复杂,不同的cron实现可能行为不同。

需要解决的问题是在DST开始时跳过一个时钟小时,在DST结束时重复一个时钟小时。如果没有特殊处理,定时任务可能根本不会运行或被调用两次。

以下说明本包如何处理DST时钟变化。

DST开始(时钟从2:00转到3:00)

在DST开始时,预定在2:00至2:59之间的定时任务将在3:00至3:59之间开始。

这样就不会错过任何定时任务,但您应该注意,某些任务可能会与其他任务重叠,而它们通常不会。

DST结束(时钟从3:00转回2:00)

在DST结束时,处理取决于cron字段中的小时表达式。如果定义了通配符或匹配2:00至3:00之间的范围,定时任务将运行两次。对于列表、递增和单个值,定时任务只运行一次。

以下表格显示了哪些表达式会导致重复,哪些不会重复

用户输入验证

为了验证用户输入的cron表达式,您可以使用包含的CronExpressionValidationRule

$rules = [
	'fieldName' => ['required', new CronExpressionValidationRule()],
]