Quart.Net 有时 运行 重叠任务
Quart.Net is Sometimes Running Overlapping Tasks
我正在使用 Quartz.Net 3.0.7
来管理调度程序。在我的测试环境中,我有两个调度程序实例 运行。我有一个测试过程在结束前运行整整 2 小时。 Quartz 配置为每 10 秒启动一次进程,我正在使用 DisallowConcurrentExecution
属性来防止任务的多个实例同时来自 运行。 80% 的时间都按预期工作。 Quartz 将启动该进程并阻止任务的任何其他实例启动,直到初始任务完成为止。如果我停止托管 Quart 的两个服务之一,那么另一个实例将在下一个 10 秒标记处接手该任务。
然而,在保持这两个 Quartz 服务 运行 48 小时不间断之后,我发现有几次出现了可怕的错误。有时主机 B 会启动任务,即使任务仍在主机 A 上执行 2 小时。有一次我什至发现该进程在主机 B 上启动了 3 次,都在 10 分钟内时期。因此,在两个小时的时间内,一个任务同时具有三个实例 运行。在这三个都完成后,Quartz 回到预期的时间表,一次只有一个实例 运行。
如果这些重叠的任务在 100% 的时间内发生,我会认为我这边有问题,但由于它似乎只在大约 20% 的时间内发生,我认为它一定是在石英实现。这是设计使然还是错误?如果我可以从 Quart.Net
捕获一个事件来告诉我另一个任务实例已经启动,我可以监听它并从 运行 停止现有任务。我只需要确保 DisallowConcurrentExecution
得到遵守并防止任务同时出现 运行 多个实例。谢谢。
编辑:
我添加了使用 context.Scheduler.GetCurrentlyExecutingJobs 的逻辑,以在我的任务启动时查找任何具有相同 JobDetail.Key 但 FireInstanceId 不同的作业。如果我找到另一个当前正在执行的作业,我将阻止此实例执行任何操作。我发现在重复的并发场景中,Quartz 报告当前没有其他作业正在执行相同的 JobDetail.Key。这应该是可能的吗?在什么情况下 Quartz.Net 会启动一个 IJob,在几分钟后失去对它作为正在执行作业的跟踪,但允许它继续执行而不取消 CancellationToken?
编辑2:
我在我的日志中发现了一个实例,其中 Quartz 按预期启动了一个任务。然后,一分钟后,Quartz 尝试启动另外 9 个实例,每个实例都有不同的 FireInstanceId。我的自定义代码阻止了 9 个额外的实例,因为它可以通过调用 GetCurrentlyExecutingJobs
获取 运行 作业列表来看到原始实例仍在运行。我仔细检查了运行时所有任务的 ConcurrentExecutionDisallowed
标志为真,所以我希望 Quartz 会阻止重复实例。这听起来像一个错误。我应该手动处理这个还是我应该期望 Quartz 做对?
编辑3:
我肯定在看两个不同的问题。在这两种情况下,Quartz.Net 使用新的 FireInstanceId 启动我的 IJob 实例,而同一个 JobKey 已经有另一个 FireInstanceId 运行。在一种情况下,我可以通过调用 GetCurrentlyExecutingJobs 看到两个 FireInstanceIds 都处于活动状态。在第二种情况下,调用 GetCurrentlyExecutingJobs 显示第一个 FireInstanceId 不再是 运行,尽管我可以从我的日志中看到原始实例仍然是 运行。这两种情况都会导致我的 IJob 运行 同时出现多个实例,这是不可接受的。通过在我的 IJob 启动时调用 GetCurrentlyExecutingJobs 来解决第一种情况很容易,但第二种情况更难。我将不得不每隔一段时间 ping GetCurrentlyExecutingJobs 并在它的 FireInstanceId 从活动列表中消失时停止任务。有没有其他人真的没有注意到这种行为?
我发现如果设置此选项,我将不再有重叠的执行作业。我仍然希望 Quartz 取消作业的取消令牌,如果它丢失了正在执行的作业。
QuartzProperties.Add("quartz.jobStore.clusterCheckinInterval", "60000");
我正在使用 Quartz.Net 3.0.7
来管理调度程序。在我的测试环境中,我有两个调度程序实例 运行。我有一个测试过程在结束前运行整整 2 小时。 Quartz 配置为每 10 秒启动一次进程,我正在使用 DisallowConcurrentExecution
属性来防止任务的多个实例同时来自 运行。 80% 的时间都按预期工作。 Quartz 将启动该进程并阻止任务的任何其他实例启动,直到初始任务完成为止。如果我停止托管 Quart 的两个服务之一,那么另一个实例将在下一个 10 秒标记处接手该任务。
然而,在保持这两个 Quartz 服务 运行 48 小时不间断之后,我发现有几次出现了可怕的错误。有时主机 B 会启动任务,即使任务仍在主机 A 上执行 2 小时。有一次我什至发现该进程在主机 B 上启动了 3 次,都在 10 分钟内时期。因此,在两个小时的时间内,一个任务同时具有三个实例 运行。在这三个都完成后,Quartz 回到预期的时间表,一次只有一个实例 运行。
如果这些重叠的任务在 100% 的时间内发生,我会认为我这边有问题,但由于它似乎只在大约 20% 的时间内发生,我认为它一定是在石英实现。这是设计使然还是错误?如果我可以从 Quart.Net
捕获一个事件来告诉我另一个任务实例已经启动,我可以监听它并从 运行 停止现有任务。我只需要确保 DisallowConcurrentExecution
得到遵守并防止任务同时出现 运行 多个实例。谢谢。
编辑: 我添加了使用 context.Scheduler.GetCurrentlyExecutingJobs 的逻辑,以在我的任务启动时查找任何具有相同 JobDetail.Key 但 FireInstanceId 不同的作业。如果我找到另一个当前正在执行的作业,我将阻止此实例执行任何操作。我发现在重复的并发场景中,Quartz 报告当前没有其他作业正在执行相同的 JobDetail.Key。这应该是可能的吗?在什么情况下 Quartz.Net 会启动一个 IJob,在几分钟后失去对它作为正在执行作业的跟踪,但允许它继续执行而不取消 CancellationToken?
编辑2:
我在我的日志中发现了一个实例,其中 Quartz 按预期启动了一个任务。然后,一分钟后,Quartz 尝试启动另外 9 个实例,每个实例都有不同的 FireInstanceId。我的自定义代码阻止了 9 个额外的实例,因为它可以通过调用 GetCurrentlyExecutingJobs
获取 运行 作业列表来看到原始实例仍在运行。我仔细检查了运行时所有任务的 ConcurrentExecutionDisallowed
标志为真,所以我希望 Quartz 会阻止重复实例。这听起来像一个错误。我应该手动处理这个还是我应该期望 Quartz 做对?
编辑3: 我肯定在看两个不同的问题。在这两种情况下,Quartz.Net 使用新的 FireInstanceId 启动我的 IJob 实例,而同一个 JobKey 已经有另一个 FireInstanceId 运行。在一种情况下,我可以通过调用 GetCurrentlyExecutingJobs 看到两个 FireInstanceIds 都处于活动状态。在第二种情况下,调用 GetCurrentlyExecutingJobs 显示第一个 FireInstanceId 不再是 运行,尽管我可以从我的日志中看到原始实例仍然是 运行。这两种情况都会导致我的 IJob 运行 同时出现多个实例,这是不可接受的。通过在我的 IJob 启动时调用 GetCurrentlyExecutingJobs 来解决第一种情况很容易,但第二种情况更难。我将不得不每隔一段时间 ping GetCurrentlyExecutingJobs 并在它的 FireInstanceId 从活动列表中消失时停止任务。有没有其他人真的没有注意到这种行为?
我发现如果设置此选项,我将不再有重叠的执行作业。我仍然希望 Quartz 取消作业的取消令牌,如果它丢失了正在执行的作业。
QuartzProperties.Add("quartz.jobStore.clusterCheckinInterval", "60000");