这周换了家新公司,刚来看到的第一个项目就是需要管理很多个job,job会在特定的时间来执行。之前看到这种需求第一时间想到的就是用控制台,但是控制台会出现人为关闭等不稳定因素。甚至还用过windows自带的计划任务程序来跑脚本,但是一直感觉这种做法不是很科学,又找不到好的方式。
来了新公司发现了Quartz调度器机制,只需要在里面设置相应的执行规则,把需要执行的job(也可以是多个job),进行绑定就可以在特定的时间执行。
具体流程我直接上代码,有兴趣的小伙伴可以去详细看看Quartz运行机制:
1、首先新建规则类:SmartTriggerUtils
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace NetCore.Quartz
{
public class SmartTriggerUtils
{
// 创建Cron 触发器
public ITrigger CreateTriggerByCron(String cron)
{
return TriggerBuilder.Create()
//错过的立即追赶,然后正常调度 WithMisfireHandlingInstructionIgnoreMisfires
//以错过的第一个频率时间立刻开始执行
//—重做错过的所有频率周期后
//——当下一次触发频率发生时间大于当前时间后,再按照正常的Cron频率依次执行
.WithCronSchedule(cron, x => x.WithMisfireHandlingInstructionIgnoreMisfires())
.WithDescription("触发规则:" + cron)
.Build();
}
//创建Interval 秒级 Trigger
public ITrigger CreateTriggerByIntervalSeconds(int millis)
{
return TriggerBuilder.Create()
//错过的立即追赶,然后正常调度
.WithSimpleSchedule(x => x.WithMisfireHandlingInstructionIgnoreMisfires()
.WithIntervalInSeconds(millis)
.RepeatForever())//每三分钟执行一次
.Build();
}
//获取每半小时执行一次的触发器
public ITrigger GetFiveMinutesTrigger()
{
lock (this)
{
return TriggerBuilder.Create()
//错过的立即追赶,然后正常调度
.WithSimpleSchedule(x => x.WithMisfireHandlingInstructionIgnoreMisfires()
.WithIntervalInMinutes(5)
.RepeatForever())//每五分钟执行一次
.Build();
}
}
}
}
这里定义了三种规则,第一种为传递string,参数详解为:
// 秒、分钟、小时、月份的哪一天、月份、星期几、年份;当前表示为:
// 每天 15:41:00生成
// 如设置: "0 41 15 * * ? *"
2、其次新建任务方法类:SmartSchedulListenner
using Quartz;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace NetCore.Quartz
{
public class SmartSchedulListenner : ISchedulerListener
{
//新增任务
public Task JobAdded(IJobDetail jobDetail, CancellationToken cancellationToken = default)
{
//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
logger.Info(jobDetail.Key.Name);
});
}
//删除任务
public Task JobDeleted(JobKey jobKey, CancellationToken cancellationToken = default)
{//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
});
}
//任务中断
public Task JobInterrupted(JobKey jobKey, CancellationToken cancellationToken = default)
{//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
logger.Info(jobKey.Group + "组 -- " + jobKey.Name + "任务中断");
});
}
//任务停止
public Task JobPaused(JobKey jobKey, CancellationToken cancellationToken = default)
{//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
logger.Info(jobKey.Group + "组 -- " + jobKey.Name + "任务停止");
});
}
//任务重新开始
public Task JobResumed(JobKey jobKey, CancellationToken cancellationToken = default)
{
//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
//logger.Info(jobKey.Group + "组 -- " + jobKey.Name + "任务重新启动");
});
}
//
public Task JobScheduled(ITrigger trigger, CancellationToken cancellationToken = default)
{
//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
});
}
//
public Task JobsPaused(string jobGroup, CancellationToken cancellationToken = default)
{
//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
logger.Info(jobGroup + "组 -- " + "任务全部停止");
});
}
//
public Task JobsResumed(string jobGroup, CancellationToken cancellationToken = default)
{
//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
logger.Info(jobGroup + "组 -- " + "任务重启");
});
}
//
public Task JobUnscheduled(TriggerKey triggerKey, CancellationToken cancellationToken = default)
{
return Task.Factory.StartNew(() =>
{
});
}
//调度器出错
public Task SchedulerError(string msg, SchedulerException cause, CancellationToken cancellationToken = default)
{
//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
//调度器报错,记录日志
logger.Error(msg);
logger.Error(cause.ToString());
});
}
//
public Task SchedulerInStandbyMode(CancellationToken cancellationToken = default)
{
return Task.Factory.StartNew(() =>
{
});
}
//调度器停止后
public Task SchedulerShutdown(CancellationToken cancellationToken = default)
{//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
//调度器将要关闭
logger.Info("定时调度器停止");
});
}
//将要关闭调度器时调用
public Task SchedulerShuttingdown(CancellationToken cancellationToken = default)
{
//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
//重新启动一个新的调度器
//并绑定任务和触发器
QuartzConfig.run();
logger.Info("定时调度器开始重启");
});
}
//调度器启动
public Task SchedulerStarted(CancellationToken cancellationToken = default)
{
//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
//启动调度器后
logger.Info("调度任务启动成功");
});
}
//调度器开始前调用
public Task SchedulerStarting(CancellationToken cancellationToken = default)
{
//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
//启动调度器后
logger.Info("调度任务开始启动...");
});
}
public Task SchedulingDataCleared(CancellationToken cancellationToken = default)
{
return Task.Factory.StartNew(() =>
{
});
}
//
public Task TriggerFinalized(ITrigger trigger, CancellationToken cancellationToken = default)
{
//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
logger.Info(trigger.Key.Name);
});
}
//
public Task TriggerPaused(TriggerKey triggerKey, CancellationToken cancellationToken = default)
{
//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
logger.Info(triggerKey.Group + "组 -- " + triggerKey.Name + "触发器停止");
});
}
//
public Task TriggerResumed(TriggerKey triggerKey, CancellationToken cancellationToken = default)
{
//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
logger.Info(triggerKey.Group + "组 -- " + triggerKey.Name + "触发器重新启动");
});
}
//
public Task TriggersPaused(string triggerGroup, CancellationToken cancellationToken = default)
{
//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
logger.Info(triggerGroup + "组 -- " + "触发器全部停止");
});
}
//
public Task TriggersResumed(string triggerGroup, CancellationToken cancellationToken = default)
{
//这里添加Nlog
var logger = NLog.Web.NLogBuilder.ConfigureNLog("nlog.config").GetCurrentClassLogger();
return Task.Factory.StartNew(() =>
{
logger.Info(triggerGroup + "组 -- " + "触发器全部重新启动");
});
}
}
}
3、新建绑定job类:QuartzConfig
using Quartz;
using Quartz.Impl;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace NetCore.Quartz
{
public class QuartzConfig
{
public QuartzConfig()
{
}
public static void run()
{
//配置默认线程池
var pairs = new System.Collections.Specialized.NameValueCollection();
//初始化线程数
pairs["quartz.threadPool.ThreadCount"] = "7";
//线程优先级
pairs["quartz.threadPool.threadPriority"] = "5";
//线程池类型
pairs["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
// pairs["startupDelay"] = "30";
pairs["org.quartz.RAMJobStore.acquireTriggersWithinLock"] = "true";
//初始化调度工厂
var schedulerFactory = new StdSchedulerFactory(pairs);
//创建一个任务调度器
var scheduler = schedulerFactory.GetScheduler();
//添加scheduler监听器
scheduler.Result.ListenerManager.AddSchedulerListener(new SmartSchedulListenner());
//开启任务调度
scheduler.Result.Start();
//创建任务 QuartzJob 绑定工作1
var jobDetail1 = JobBuilder.Create<QuartzJob>()
.WithIdentity("QuartzJob", "maintenance")
.WithDescription("生成测试任务")
.Build();
//创建任务2 QuartzJob2 绑定工作1
var jobDetail2 = JobBuilder.Create<QuartzJob2>()
.WithIdentity("QuartzJob2", "maintenance")
.WithDescription("生成测试任务")
.Build();
//创建任务3 QuartzJob3 绑定工作1
var jobDetail3 = JobBuilder.Create<QuartzJob3>()
.WithIdentity("QuartzJob3", "maintenance")
.WithDescription("生成测试任务")
.Build();
SmartTriggerUtils Trigges = new SmartTriggerUtils();
//绑定Job和Trigger
IReadOnlyDictionary<IJobDetail, IReadOnlyCollection<ITrigger>> jobsAndTriggers = null;
// 系统自动创建任务,秒、分钟、小时、月份的哪一天、月份、星期几、年份;当前表示为: 每天 15:41:00生成
// "MaintenceCreateTaskCron": "0 41 15 * * ? *",
jobsAndTriggers
= new Dictionary<IJobDetail, IReadOnlyCollection<ITrigger>>
{
// 测试任务1
{ jobDetail1,
new List<ITrigger> { Trigges.CreateTriggerByCron("0 23 13 * * ? *") }.AsReadOnly()
},
// 测试任务2
{ jobDetail2,
new List<ITrigger> { Trigges.CreateTriggerByCron("0 23 13 * * ? *") }.AsReadOnly()
},
// 测试秒级任务 多少秒执行一次
{ jobDetail3,
new List<ITrigger> { Trigges.CreateTriggerByIntervalSeconds(60) }.AsReadOnly()
}
};
//将任务交由调度器管理
scheduler.Result.ScheduleJobs(jobsAndTriggers, false, System.Threading.CancellationToken.None);
}
}
}
4、注册服务(在Startup下ConfigureServices里)
//注册服务
services.AddSingleton<ISchedulerFactory, StdSchedulerFactory>();
//启动quzrzt任务
QuartzConfig.run();
