DotNetCore跨平臺~Quartz熱部署的福音~監控資料夾的變化
在DotNetCore出來之後,同時也使用了quartz進行排程中心的設計,將它做到docker裡方便部署,在之前的quartz版本里支援配置檔案的方式,而現在不支援了,我們應該去想一下,為什麼不去支援配置檔案?當然大叔也為配置檔案設計了支援的方式,但我們還是應該想想作者為什麼不去支援配置?
熱插拔,服務發現?
和上面兩個概念可能有點關係,熱插拔很容易理解,就是把dll模組放到正在執行的專案時,它可以直接啟動,這個功能對排程中心來說,很是必要,因為你可能需要按著不同的功能設計一些服務job,而這些服務沒有什麼聯絡,每個job功能單一,如果做成熱部署,挺好!而服務發現在最近<微服務>裡很是槍眼,今天說的服務發現並不是它,而是dotnet core公開的對資料夾的監控,其實就是一種事件機制,當windows底層資料夾改變時(增,刪,改檔案),會向上觸發對應的事件,而我們只要去訂閱它即可,非常的鬆耦合!
公開的事件
var watcher = new FileSystemWatcher(); watcher.Path = AppDomain.CurrentDomain.BaseDirectory; watcher.NotifyFilter = NotifyFilters.Attributes | NotifyFilters.CreationTime | NotifyFilters.DirectoryName| NotifyFilters.FileName | NotifyFilters.LastAccess | NotifyFilters.LastWrite | NotifyFilters.Security | NotifyFilters.Size; watcher.Filter= "*.dll"; // quartz執行時,可以新增新job,但不能覆蓋,刪除等 watcher.Created += new FileSystemEventHandler((o, e) => { foreach (var module in Assembly.LoadFile(e.FullPath).GetModules()) { foreach (var type in module.GetTypes().Where(i => i.BaseType == typeof(JobBase))) { JoinToQuartz(type); } } }); //Start monitoring. watcher.EnableRaisingEvents = true;
將job新增到Quartz需要在初始化和資料夾監控兩個地方用到,所以我們進行了抽象,把它提到一個委託裡,使用.net4.0的Actioin<T>委託來實現最為合適了!
Action<Type> JoinToQuartz = (type) => { var obj = Activator.CreateInstance(type); string cron = type.GetProperty("Cron").GetValue(obj).ToString(); var jobDetail = JobBuilder.Create(type) .WithIdentity(type.Name) .Build(); var jobTrigger = TriggerBuilder.Create() .WithIdentity(type.Name + "Trigger") .StartNow() .WithCronSchedule(cron) .Build(); StdSchedulerFactory.GetDefaultScheduler().Result.ScheduleJob(jobDetail, jobTrigger); Console.ForegroundColor = ConsoleColor.Yellow; Console.WriteLine($"新添加了一個服務{nameof(type)},通過心跳Job自動被載入!"); };
大叔把它應用到了排程中心上,具體就是當除錯專案裡有新的模組DLL出現後,自動將它新增到quartz的列表裡,然後當然它有自己的cron表示式去控制自己的排程週期,你是定點地還是週期執行完成由自己的job去控制,如果有新功能,就加新Job,是否有點單一職責和開閉原則的意思!
JobBase,所有模組的功能Job都要繼承它,可以根據自己的情況,實現cron和業務ExcuteJob方法!
[DisallowConcurrentExecution()] public abstract class JobBase : IJob { #region IJob 成員 public Task Execute(IJobExecutionContext context) { try { Console.ForegroundColor = ConsoleColor.Red; Console.WriteLine(DateTime.Now.ToString() + "{0}這個Job開始執行", context.JobDetail.Key.Name); ExcuteJob(context); return Task.CompletedTask; ; } catch (Exception ex) { LoggerFactory.CreateLog().Logger_Debug(this.GetType().Name + "error:" + ex.Message); throw; } } #endregion /// <summary> /// 執行計劃,子類可以重寫 /// </summary> public virtual string Cron => "0/5 * * * * ?"; /// <summary> /// Job具體類去實現自己的邏輯 /// </summary> protected abstract void ExcuteJob(IJobExecutionContext context); }
下面看其中一個業務Job的實現,它主要由排程計劃cron和業務執行方法ExcuteJob組成
/// <summary> /// 傳送訊息 /// </summary> public class SendEmailJob : JobBase { public override string Cron => "0/2 * * * * ?"; protected override void ExcuteJob(IJobExecutionContext context) { Console.WriteLine("傳送Email"); LoggerFactory.CreateLog().Logger_Debug("傳送Email:" + DateTime.Now); } }
當我們把這個專案釋出到dotnet core之後,可以設計一個web api /web mvc管理UI,然後去檢視和管理自己的任務,現在quartz2.x裡的crystal管理工具已經用不了了,所以咱們還是DIY一下吧!哈哈!
可以檢視任務列表,管理它們的啟動與停止的狀態!
感謝各位的閱讀!