我在 Go 项目中使用 github.com/go-co-op/gocron 包来安排任务。该作业设置为每 2 分钟运行一次,但在某些情况下,该任务可能需要比该时间间隔更长的时间(例如,该作业需要 7 分钟才能完成)。长时间运行的作业完成后,会连续触发多个作业实例,从而导致重叠执行。
func newScheduler(loc *time.Location) {
e := gocron.NewScheduler(loc)
e.SingletonModeAll()
e.Every("2m").Do(func() {
Logger.Warn("Task Started at: " + time.Now().Format("2006-01-02 15:04:05"))
err := tasks.MyTask()
if err != nil {
Logger.Error("Error occurred during task execution: ", err)
}
Logger.Warn("Task Completed at: " + time.Now().Format("2006-01-02 15:04:05"))
})
e.StartAsync()
select {}
}
问题: 当作业花费的时间超过计划的时间间隔(例如,7 分钟而不是 2 分钟)时,在长时间运行的作业完成后,作业的多个实例将连续执行。这会导致性能问题和重叠的作业。
问题: 有没有一种方法可以确保作业执行后只有一个作业实例运行,后续作业等到前一个实例完成后才开始,并且应该根据下一个时间间隔只运行一次?
我尝试过的: 我启用了 SingletonModeAll(),但是当由于长时间运行的任务而错过间隔时,它不会阻止执行背靠背作业。
期望的结果: 我想确保在执行作业后,它应该忽略堆积的作业,并且不应该背靠背运行,即使作业花费的时间比计划的时间间隔长。
任何关于如何在 GoCron 中处理此问题或替代方法的指导将不胜感激!
您正在使用旧的 v1 API,上面写着:
如果特定作业的先前实例尚未完成其运行,SingletonModeAll 会阻止新作业启动
警告:如果您的工作量将继续堆积,超出工人的极限能力,请勿使用此模式。
你要使用的是`SetMaxConcurrentJobs:
限制可以同时运行的作业数量。
RescheduleMode
:
默认情况下,如果有最大限制 设置并发作业并达到限制,作业将 跳过它的运行并在计划中的下一个事件中重试
所以
e.SetMaxConcurrentJobs(1, gocron. RescheduleMode)
github.com/go-co-op/gocron/v2
,其中有 WithLimitConcurrentJobs
:
e, err := gocron.NewScheduler(gocron.WithLimitConcurrentJobs(1, gocron.LimitModeReschedule))