一:业务需求:
项目需要在不同时刻,执行一个或很多个不同的作业。
Windows执行计划这时并不能很好的满足需求了,迫切需要一个更为强大,方便管理,集群部署的作业调度框架。
二:介绍
Quartz一个开源的作业调度框架,OpenSymphony的开源项目。Quartz.Net 是Quartz的C#移植版本。
特性:
1:支持集群,作业分组,作业远程管理。
2:自定义精细的时间触发器,使用简单,作业和触发分离。
3:数据库支持,可以寄宿Windows服务,WebSite,winform等。
三:使用的方法:
1.名词的解释:
Scheduler 作业调度器。
IJob 作业接口,继承并实现Execute, 编写执行的具体作业逻辑。
JobBuilder 根据设置,生成一个详细作业信息(JobDetail)。
TriggerBuilder 根据规则,生产对应的Trigger
2.学习的官网
Quartz.Net官方2.X教程 http://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/index.html
Quartz.Net开源地址 https://github.com/quartznet/quartznet
3.Nuget安装
PM> Install-Package Quartz
4.代码解释:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Quartz;
using Quartz.Impl;
using System.Collections.Specialized;
namespace Portal.JobScheduler
{
public class QuartzManager<T> where T:class,IJob
{
//调度程序的工厂的接口中 实例一个具体的调度方法
private static ISchedulerFactory schedulerFactory = new StdSchedulerFactory();
//JOb群组名
private static string JOB_GROUP_NAME = "JOBGROUP_NAME";
//触发器群
private static string TRIGGER_GROUP_NAME = "TRIGGERGROUP_NAME";
/// <summary>
/// 添加一个定时任务,使用默认的任务组名,触发器名,触发器组名
/// </summary>
/// <param name="pStrJobName">任务名</param>
/// <param name="pStrCronExpress">触发器表达式</param>
public static void AddJob(string pStrJobName, string pStrCronExpress)
{
try
{
//接口中获取调度工厂的 GetScheduler() 方法
IScheduler sched = schedulerFactory.GetScheduler();
//创建任务
IJobDetail job = JobBuilder.Create<T>().WithIdentity(pStrJobName, JOB_GROUP_NAME).Build();
//创建触发器
ITrigger trigger = TriggerBuilder.Create()
.WithIdentity(pStrJobName, TRIGGER_GROUP_NAME)
.WithCronSchedule(pStrCronExpress)
.Build();
sched.ScheduleJob(job, trigger);
sched.Start();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
/// <summary>
/// 移除一个任务(使用默认的任务组名,触发器名,触发器组名)
/// </summary>
/// <param name="pStrJobName"></param>
public static void RemoveJob(string pStrJobName)
{
try
{
IScheduler sched = schedulerFactory.GetScheduler();
JobKey jobkey = new JobKey(pStrJobName);
TriggerKey triggerKey = new TriggerKey(pStrJobName, TRIGGER_GROUP_NAME);
//停止触发器
sched.PauseTrigger(triggerKey);
//移除触发器
sched.UnscheduleJob(triggerKey);
//删除任务
sched.DeleteJob(jobkey);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
/// <summary>
/// 修改一个任务的触发时间(使用默认的任务组名,触发器名,触发器组名)
/// </summary>
/// <param name="pStrJobName">任务名</param>
/// <param name="pStrCronExpress">触发器表达式</param>
public static void ModifyJobTime(string pStrJobName, string pStrCronExpress, IDictionary<string, object> pDictionary)
{
try
{
IScheduler sched = schedulerFactory.GetScheduler();
TriggerKey triggerKey = new TriggerKey(pStrJobName, TRIGGER_GROUP_NAME);
ICronTrigger trigger = (ICronTrigger)sched.GetTrigger(triggerKey);
if (trigger == null)
{
return;
}
RemoveJob(pStrJobName);
AddJob(pStrJobName, pStrCronExpress);
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
/// <summary>
/// 开启所有定时任务
/// </summary>
public static void startJobs()
{
try
{
IScheduler sched = schedulerFactory.GetScheduler();
sched.Start();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
/// <summary>
/// 关闭所有的定时任务
/// </summary>
public static void shutdownJobs()
{
try
{
IScheduler sched = schedulerFactory.GetScheduler();
if (!sched.IsShutdown)
{
sched.Shutdown();
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
/// <summary>
/// 恢复所有的任务
/// </summary>
public static void ResumeAllJobs()
{
try
{
IScheduler sched = schedulerFactory.GetScheduler();
if (!sched.IsShutdown)
{
sched.ResumeAll();
}
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
/// <summary>
/// 暂停所有的作业
/// </summary>
public static void PauseAllJobs()
{
try
{
IScheduler sched = schedulerFactory.GetScheduler();
sched.PauseAll();
}
catch (Exception e)
{
throw new Exception(e.Message);
}
}
}
}
Asp。net调用:
在global文件中进行配置
private void RegisterJob()
{
QuartzManager<SHiddenDangerCaution>.AddJob("SHiddenDangerCautionInfo", "0 0 08 ? * *");
}
调度类的写法:
public class SyncWeatherInfoJob:IJob
{
public void Execute(IJobExecutionContext context)
{
UpdateWeatherForecast();
}
/// <summary>
/// 更新气象实况信息
/// </summary>
public void UpdateWeatherForecast()
{
WeatherForecast.InsertWeatherInfo(); --这里的代码就不贴出来
}
}
这样就完成了调度任务
CrystalQuartz 远程管理
CrystalQuartz开源的地址 https://github.com/guryanovev/CrystalQuartz
但如果想方便的知道某个作业执行情况,需要暂停,启动等操作行为,这时候就需要个Job管理的界面。
接下来介绍Quartz.NET如何进行远程job管理,如图:
代码:
一:作业服务端
static void Main(string[] args)
{
var properties = new NameValueCollection();
properties["quartz.scheduler.instanceName"] = "RemoteServerSchedulerClient";
// 设置线程池
properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
properties["quartz.threadPool.threadCount"] = "5";
properties["quartz.threadPool.threadPriority"] = "Normal";
// 远程输出配置
properties["quartz.scheduler.exporter.type"] = "Quartz.Simpl.RemotingSchedulerExporter, Quartz";
properties["quartz.scheduler.exporter.port"] = "556";
properties["quartz.scheduler.exporter.bindName"] = "QuartzScheduler";
properties["quartz.scheduler.exporter.channelType"] = "tcp";
var schedulerFactory = new StdSchedulerFactory(properties);
var scheduler = schedulerFactory.GetScheduler();
var job = JobBuilder.Create<PrintMessageJob>()
.WithIdentity("myJob", "group1")
.Build();
var trigger = TriggerBuilder.Create()
.WithIdentity("myJobTrigger", "group1")
.StartNow()
.WithCronSchedule("/10 * * ? * *")
.Build();
scheduler.ScheduleJob(job, trigger);
scheduler.Start();
}
public class PrintMessageJob : IJob
{
public void Execute(IJobExecutionContext context)
{
Console.WriteLine("Hello!");
}
}
二:作业远程管理端,无需写任何代码,引用官方程序集,嵌入到已有的web网站。
PM> Install-Package CrystalQuartz.Remote
Webconfig 需要配置的地方
<configuration>
<crystalQuartz>
<provider>
<add property="Type" value="CrystalQuartz.Core.SchedulerProviders.RemoteSchedulerProvider, CrystalQuartz.Core" />
<add property="SchedulerHost" value="tcp://127.0.0.1:556/QuartzScheduler" /> <!--TCP监听的地址-->
</provider>
</crystalQuartz>
<system.webServer>
<!-- Handler拦截处理了,输出作业监控页面-->
<handlers>
<add name="CrystalQuartzPanel" verb="*" path="CrystalQuartzPanel.axd" type="CrystalQuartz.Web.PagesHandler, CrystalQuartz.Web" />
</handlers>
</system.webServer>
</configuration>