Quartz.NET的使用(附源碼)

簡介

  雖然Quartz.NET被園子裏的大神們寫爛了,本身仍是整理了一篇,結尾會附上源碼地址。html

  Quartz.NET是一款功能齊全的開源做業調度框架,小至的應用程序,大到企業系統均可以適用。Quartz是做者James House用JAVA語言編寫的,而Quartz.NET是從Quartz移植過來的C#版本。git

  在通常企業,能夠利用Quartz.Net框架作各類的定時任務,例如,數據遷移、跑報表等等。github

  另外還有一款Hangfire https://www.hangfire.io/,也是做業調度框架,有自帶監控web後臺,比Quartz.Net更加易用,簡單。可是Cron最低只支持到分鐘級。然而Hangfire不是今天的主角,有機會再介紹。web

簡單例子

新建一個控制檯項目,經過Nuget管理下載Quartz包框架

using System; using System.Collections.Specialized; using Quartz; using Quartz.Impl; namespace QuartzDotNetDemo { class Program { static void Main(string[] args) { //建立一個調度器工廠
            var props = new NameValueCollection { { "quartz.scheduler.instanceName", "QuartzDotNetDemo" } }; var factory = new StdSchedulerFactory(props); //獲取調度器
            var sched = factory.GetScheduler(); sched.Start(); //定義一個任務,關聯"HelloJob"
            var job = JobBuilder.Create<HelloJob>() .WithIdentity("myJob", "group1") .Build(); //由觸發器每40秒觸發執行一次任務
            var trigger = TriggerBuilder.Create() .WithIdentity("myTrigger", "group1") .StartNow() .WithSimpleSchedule(x => x .WithIntervalInSeconds(40) .RepeatForever()) .Build(); sched.ScheduleJob(job, trigger); } } public class HelloJob : IJob { public void Execute(IJobExecutionContext context) { Console.WriteLine("你好"); } } }
View Code

一個簡單的調度任務流程以下:ide

概念

  有幾個重要類和概念須要瞭解一下:ui

  • IScheduler - 與調度器交互的主要API.
  • IJob -由執行任務實現的接口。
  • IJobDetail - 定義Job實例
  • ITrigger - 按照定義的時間讓任務執行的組件.
  • JobBuilder - 用於定義或者建立JobDetai
  • TriggerBuilder -用於定義或生成觸發器實例

  他們之間的關係大概以下:spa

  當有空閒線程同時,到了該執行的時間,那麼就會由Trigger去觸發綁定的Job執行它的Excute方法,假如此次沒執行完,卻到了下一次的運行時間,若是有空閒線程就仍然會再次執行。可是若是沒有空閒線程,會等到騰出空閒的線程纔會執行,可是超過quartz.jobStore.misfireThreshold設置的時間就會放棄此次的運行。線程

  固然也能夠在Job貼上DisallowConcurrentExecution標籤讓Job進行單線程跑,避免沒跑完時的重複執行。3d

改造

  在第一個簡單的demo裏是沒法良好的在實際中使用,所以咱們須要改造一下。

    須要的第三方包:

  • Autofac version="4.6.2"
  • Autofac.Extras.Quartz version="3.4.0"
  • Common.Logging version="3.4.1"
  • Common.Logging.Core version="3.4.1"
  • Common.Logging.Log4Net1213 version="3.4.1"
  • log4net version="2.0.3"
  • Newtonsoft.Json version="10.0.3"
  • Quartz version="2.6.1"
  • Topshelf version="4.0.3"
  • Topshelf.Autofac version="3.1.1"
  • Topshelf.Log4Net version="3.2.0"
  • Topshelf.Quartz version="0.4.0.1"

Topshelf

  Topshelf是一款爲了方便安裝部署在Windows系統下而誕生的宿主框架,它基於控制檯項目,爲開發人員帶來更方便的調試和部署。

  官網:https://topshelf.readthedocs.io/en/latest/index.html

  那咱們能夠在Program.cs裏寫入如下代碼:

using Topshelf; using Topshelf.Autofac; namespace QuartzDotNetDemo { class Program { static void Main(string[] args) { HostFactory.Run(config => { config.SetServiceName(JobService.ServiceName); config.SetDescription("Quartz.NET的demo"); config.UseLog4Net(); config.UseAutofacContainer(JobService.Container); config.Service<JobService>(setting => { JobService.InitSchedule(setting); setting.ConstructUsingAutofacContainer(); setting.WhenStarted(o => o.Start()); setting.WhenStopped(o => o.Stop()); }); }); } } }
View Code

JobService

  此類用來讀取配置信息、初始化調度任務和注入ioc容器

public class JobService { #region 初始化
        private static readonly ILog Log = LogManager.GetLogger(typeof(JobService)); private const string JobFile = "JobsConfig.xml"; private static readonly string JobNamespceFormat; public static readonly string ServiceName; private static readonly Jobdetail[] JobList; public static IContainer Container; static JobService() { var job = JobFile.XmlToObject<JobsConfig>(); ServiceName = job.Quartz.ServiceName; JobNamespceFormat = job.Quartz.Namespace; JobList = job.Quartz.JobList.JobDetail; Log.Info("Jobs.xml 初始化完畢"); InitContainer(); } #endregion

        /// <summary>
        /// 初始化調度任務 /// </summary>
        /// <param name="svc"></param>
        public static void InitSchedule(ServiceConfigurator<JobService> svc) { svc.UsingQuartzJobFactory(Container.Resolve<IJobFactory>); foreach (var job in JobList) { svc.ScheduleQuartzJob(q => { q.WithJob(JobBuilder.Create(Type.GetType(string.Format(JobNamespceFormat, job.JobName))) .WithIdentity(job.JobName, ServiceName) .Build); q.AddTrigger(() => TriggerBuilder.Create() .WithCronSchedule(job.Cron) .Build()); Log.InfoFormat("任務 {0} 已完成調度設置", string.Format(JobNamespceFormat, job.JobName)); }); } Log.Info("調度任務 初始化完畢"); } /// <summary>
        /// 初始化容器 /// </summary>
        private static void InitContainer() { var builder = new ContainerBuilder(); builder.RegisterModule(new QuartzAutofacFactoryModule()); builder.RegisterModule(new QuartzAutofacJobsModule(typeof(JobService).Assembly)); builder.RegisterType<JobService>().AsSelf(); var execDir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var files = Directory.GetFiles(execDir, "QuartzDotNetDemo.*.dll", SearchOption.TopDirectoryOnly); if (files.Length > 0) { var assemblies = new Assembly[files.Length]; for (var i = 0; i < files.Length; i++) assemblies[i] = Assembly.LoadFile(files[i]); builder.RegisterAssemblyTypes(assemblies) .Where(t => t.GetInterfaces().ToList().Contains(typeof(IService))) .AsSelf() .InstancePerLifetimeScope(); } Container = builder.Build(); Log.Info("IOC容器 初始化完畢"); } public bool Start() { Log.Info("服務已啓動"); return true; } public bool Stop() { Container.Dispose(); Log.Info("服務已關閉"); return false; } }
View Code

觸發器類型

  一共有4種:

  • WithCalendarIntervalSchedule
  • WithCronSchedule
  • WithDailyTimeIntervalSchedule
  • WithSimpleSchedule

  在項目中使用的是WithCronSchedule,由於cron表達式更加靈活、方便。

Cron表達式

字段名 是否必填 值範圍 特殊字符
Seconds YES 0-59 , - * /
Minutes YES 0-59 , - * /
Hours YES 0-23 , - * /
Day of month YES 1-31 , - * ? / L W
Month YES 1-12 or JAN-DEC , - * /
Day of week YES 1-7 or SUN-SAT , - * ? / L #
Year NO empty, 1970-2099 , - * /

例子:

  "0 0/5 * * * ?"    ---- 每5分鐘觸發一次

  "10 0/5 * * * ?"   -----每5分鐘觸發一次,每分鐘10秒(例如:10:00:10 am,10:05:10,等等)

  "0 0/30 8-9 5,20 * ?" ----在每月的第5到20個小時之間,每隔半小時就會觸發一個觸發點。請注意,觸發器不會在上午10點觸發,僅在8點,8點30分,9點和9點30分

BaseJob

  咱們定義一個BaseJob寫入公共處理邏輯,例如:業務邏輯禁用、公共異常日誌消息推送等等。再由具體的Job去繼承重寫基類的ExecuteJob,簡單的適配器模式運用。

public abstract class BaseJob : IJob { protected readonly CommonService CommonService; protected BaseJob(CommonService commonService) { CommonService = commonService; } public void Execute(IJobExecutionContext context) { //公共邏輯
 CommonService.Enabled(); //job邏輯
 ExecuteJob(context); } public abstract void ExecuteJob(IJobExecutionContext context); }
View Code

 

結束

  最後按照慣例雙手奉上demo源碼。https://github.com/SkyChenSky/QuartzDotNetDemo.git

  若是錯誤麻煩在下面評論指出,我會及時修改。

相關文章
相關標籤/搜索