部署于IIS的Quartz.NET定时任务每日指定时间触发4次如何解决
问题根因
你遇到的多次触发问题核心是IIS应用程序池配置了多工作进程:你当前的Scheduler单例是进程内的静态单例,若IIS应用程序池的「最大工作进程数」设置为4,每个独立进程都会初始化一个Scheduler实例,各自加载触发器执行任务,就会出现间隔几毫秒触发4次的现象。
你添加.EndingDailyAfterCount(1)后任务不触发,大概率是你启动服务时已经过了当日配置的00:10 UTC时间,当日的执行计数已经用完,又没有配置跨天重置、错过触发策略导致。
修复方案
1. 优先修复多进程重复调度问题(必做)
二选一即可:
- 方案A(轻量,适合单服务器部署):打开IIS管理器,找到对应应用程序池→高级设置→将「最大工作进程数」调整为
1,同时关闭IIS的自动回收:将「闲置超时(分钟)」设为0,「定期回收时间间隔(分钟)」设为0,避免进程意外退出导致调度丢失。 - 方案B(稳定,适合多实例/集群部署):开启Quartz.NET的集群模式,使用数据库持久化作业和触发器信息,此时多进程下Quartz会自动保证同一时间只有一个实例触发作业。
2. 优化触发器配置(推荐)
每日固定时间触发的场景,直接使用Cron触发器比24小时间隔触发器更稳定,不会出现调度时间漂移问题,配置如下:
public static async Task Start() { // 先判断作业是否已存在,避免重复添加调度 if (await scheduler.CheckExists(new JobKey("CustomerEventAssigningJob"))) { return; } await scheduler.Start(); IJobDetail job = JobBuilder.Create<CustomerEventAssigningJob>() .WithIdentity("CustomerEventAssigningJob") .Build(); // Cron表达式:每天UTC时间00:10触发一次,格式:秒 分 时 日 月 周 年 ITrigger trigger = TriggerBuilder.Create() .WithIdentity("CustomerEventAssigningJob") .WithCronSchedule("0 10 0 ? * * *", c => c.InTimeZone(TimeZoneInfo.Utc)) // 配置错过触发的策略:错过后立即执行一次 .WithMisfireHandlingInstructionFireAndProceed() .Build(); await scheduler.ScheduleJob(job, trigger); }
3. 额外兜底配置
给作业类添加[DisallowConcurrentExecution]特性,禁止同一个作业实例并发执行,避免极端情况下的重复执行:
[DisallowConcurrentExecution] public class CustomerEventAssigningJob : IJob { // 你的作业逻辑 }
如果要保留原来的DailyTimeIntervalSchedule写法,调整配置如下即可,首次启动如果过了当日执行时间,会在第二天触发:
ITrigger trigger = TriggerBuilder.Create() .WithIdentity("CustomerEventAssigningJob") .WithDailyTimeIntervalSchedule(s => s.OnEveryDay() .StartingDailyAt(TimeOfDay.HourAndMinuteOfDay(00, 10)) .WithIntervalInHours(24) .EndingDailyAfterCount(1) .InTimeZone(TimeZoneInfo.Utc) ) .WithMisfireHandlingInstructionFireAndProceed() .Build();
内容的提问来源于stack exchange,提问作者blawal sarfraz
相关产品推荐
相关产品推荐

