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