【框架學習與探究之定時器--Quartz.Net 】

分類:IT技術 時間:2017-09-25

聲明


本文歡迎轉載原文地址:http://www.cnblogs.com/DjlNet/p/7572174.html


前言

這裏相信大部分玩家之前現在都應該有過使用定時器的時候或者需求,例如什麽定時發送郵件通知,定時篩選取消客戶下單未支付的訂單,定時數據備份或者歸檔清洗什麽的諸如此類的需求,都是定時的作用的地方,類似比如:Windows的計劃任務、數據庫的計劃任務都是同樣體現,那麽相關於這方面的輪子或者發動機就孕育而生了,也有一直一來沒怎麽人使用的微軟框架自帶5種Timer系列等等......
額,關於今天要說的這個定時器框架,相信無論是Java還是.net開發者都肯定聽說過了,當然這個定時器有些年生了是個老字號了並不表示它就真的老了哦,去github:https://github.com/quartznet/quartznet看了才知道,雖然是移植過來的但是作者是一個人在維護呀,還很積極在commit和解答issues,這裏還是佩服一下作者的勇氣和那份責任,順手Star一下加加油,而且最新的3.x也正在開發基於.net標準的做新的nuget package https://www.nuget.org/packages/Quartz/3.0.0-alpha3 開發,這裏博主大致使用一下主要有一個亮點是把以前的依賴包都整合了,體現就是一個nuget包就OK了看不見什麽Common.Logging之類的了,其中還有些Feature或者Fixes(見3.X文檔),期待穩定正式版吧!!!...
然後關於這個框架的自述或者介紹什麽的,園子文章很多啦或者官方文檔https://www.quartz-scheduler.net介紹的都挺清楚的,其中文檔中有12個學習課程(其中發現園友對文檔的中文翻譯,把園中關於此框架的部分文章看了一下,具體想去了解關鍵字搜索即可,不過較多是大致介紹和簡單使用的居多,部分都是自我集成在自己或者公司的系統中去了,形成系統中的一環或者整個任務調度平臺覆蓋到系統層面之上,所以看如何設計整合和正確姿勢使用才是關註的重點嘛!!),全部刷一遍也費不了多少時間的,也就是少幾集電視嘛,然後這樣就會對框架設計或者學習使用都基本有個大致了解,後面催牛的時候不至於讓人家以為你在瞎BB吶,哈哈。那麽,今天我們寫文是為了記錄什麽吶?額,主要是博主本身在學習過程的遇到一些不解或者需要劃重點的東西記錄一下吧,233333......


Quartz.Net框架設計概覽

這裏有挺多的關鍵詞構成了整個關系鏈的組織,俗話說得好,一張圖勝過幾百上千字,所以這裏博主靠著拙劣的構想腦回路簡述一下框架帶來的大體設計思想。

額,這張圖也花了一兩小時完成責在歸納了關於此框架整體結構和組織構成,從中一些備註和標識可以看出,Quarzt.Net再設計上面還是中規中矩,能考慮到的都盡可能考慮了,例如什麽具體執行任務與觸發器以及調度器三者分離,實現了組件職責單一原則同時吶又可以復用組件一舉兩得,這樣一來開發者就就可以按組件開發自由組合,再者就是運用了些許設計模式以及面向接口抽象編程的思想設計模式上面的功效就是讓代碼實現了抽象和細節剝離,也就是封裝隔離了變化點,讓後面的需求或者變化盡可能得可以掌控以助於對整體結構的造成沖擊力降到最低,然後基於面向接口編程也使得後期開發者自主實現可替換性的組件替換時有了機會,所以從這個層面看一個框架或者一個組件,就可以大致知道作者當初在設計的時候,為什麽要這樣,以至於這樣之後帶來的好處,什麽擴展性、易用性、靈活性等等也是從中體現的吧....那麽在學習了人家的設計思想之後,再看看自己系統的代碼可謂是有心無力呀,當然拉老項目固然是如此,不過呢對一個人思想上面的影響效果遠大於一行代碼來的更加長遠,所以面對新項目的時候就可得好好構想一下,運用一下所謂的平衡術( 只有合適的框架沒有最好的框架 )....


Quartz.Net文檔劃重點與驗證

這裏著重記錄一下文檔中個人覺得比較關鍵之處,此外會用代碼的方式去驗證,做到斤斤計較,哈哈,由於2.X與3.X差距還是有的,但是3.X還沒正式版,所以我們的系統中集成的還是2.X,那麽我們還是針對2.X文檔來做學習哈,不過3.X文檔博主已經擼了一遍了差距甚小,以及使用方式基本相似的,具體看版本遷移中的介紹也行...


Job註意事項

這裏在官方文檔Job一章中也有詳細介紹,但是博主這裏用自己的話理解一下,當然英文還可以的童鞋可以去看文檔,博主還要翻譯插件才能湊合閱讀吶...

1、關於IJob與IJobDetail註意點實現接口IJob的類的實例只是代表了要具體執行的任務邏輯而已,而實現了IJobDetail的類的實例才是包含此任務的細節,通過JobBuilder.Create創建,但是這裏的創建也正如上圖所訴不是“真正的創建”而是傳遞了JobType在JobDetial中保存引用而已,而後面具體在scheduler.JobFactory中來接管IJob具體實例的創建工作,這樣一來你的ioc容器就可以在自定義的XXXJobFactory中去自定義NewJob的創建過程,註入你的XXXService或者XXXRepository,當然也可以直接使用ServiceLoader.Resolve服務定位器模式在Execute中直接解析拿出來使用也可以,但是註意一點Quartz.Net是每次執行Job的時候都是會新創建一個Job實例的,所以註意ioc容器註入對象的生命周期的合理性。 大致去nuget上面搜索一下(某些包最近commit時間略顯久遠了),autofac、unity、Ninject都提供了第三方集成Quarzt.Net包,大致看了一下代碼量很少只有幾個類而已,編寫套路大體相近某些還接管了ISchedulerFactory創建等,所以自己需要為Quarzt集成第三方ioc的時候,可以考慮借鑒代碼自己實現。
2、JobDetail關鍵屬性與Job.Execute異常處理
(1)當一個jobDetail的job運行執行的時間大於它的trigger觸發器的間隔調度時間的時候,就會發生它的上次任務還沒運行完,接著又開始了下一個任務,或者多個trigger同時觸發執行同一個jobDetail的任務的時候都會造成這個jobDetail的job任務並發執行,通過在YourJob:IJobYourJob打上[DisallowConcurrentExecution],其實就是一個簡單的屬性類標記一下這個類而已,然後作用於具體對應的JobDetial實例(這句話很關鍵),然後JobDetail的Job執行邏輯在上述兩種情況下都可以按照理想執行了,以上博主已經通過代碼驗證過了哈,註意:多個trigger綁定同一個jobdetail需要jobDetail->StoreDurably() +trigger-> ForJob()
(2)YourJob標記: [PersistJobDataAfterExecution] 可以記住jobDetail.JobDataMap的值,所以你可以在job的執行中修改它的值,在下一次執行時候可以拿到更新之後的值拉,所以在這種情況下需要記住上次狀態,當然就需要 [DisallowConcurrentExecution] 來做支持拉,這個自然是可以理解的
(3)Durability 持久的存儲作用於jobdetail,RequestsRecovery 請求恢復作用於jobdetail當出現崩潰類似場景時使用, JobExecutionException 當job執行時需要使用try-catch來截獲所有異常,且再次向上次拋出異常需要包裝成Quartz認識的異常類型JobExecutionException ,且可以設置JobExecutionException 的可用屬性,當然你可以使用BaseJob之類的或者AOP(castle dynamic proxy)的方式來實現job執行當中的日誌、異常處理等


Trigger其他說明

Trigger:上圖基本介紹的差不多了,這裏補充一下Priority優先級默認是5,當出現資源爭搶的時候例如:線程不夠,會按照優先級來分配資源執行,以及每種Trigger有自己對應的熄火指令 Misfire Instructions就是在調度器關閉或者應用程序結束的時候或者調度線程資源不夠的時候會發現Trigger暫時性的熄火,默認情況下直接使用智能策略就行了


JobStores 持久化與 Clustering 集群

這裏官方對JobStores提供了兩種模式,https://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/job-stores.html,其中一般情況還是推薦使用 RAMJobStore,因為不論是存儲拿數據還是CPU級別的調度都是最佳的,但是缺點也是比較明顯的就是對需要持久化的信息在應用程序重啟之後就丟失了,例如XXJob的上次激發時間最後執行時間等,所以框架自身提供了AdoJobStore 可以找到對應的** DB Provider 配置** 即可,然後 Clustering 集群肯定是基於上面的 AdoJobStore 數據庫存儲模式下的,可以解決負載均衡和故障轉移的功能。
這裏博主將會做實驗去驗證,同時在園子中搜索發現已經有同學去實踐了,這裏引用一下各位大大的博文地址(應該不會介意,嘻嘻),大家也可以參考學習:
http://www.cnblogs.com/knowledgesea/p/5145239.html Quartz.net持久化與集群部署開發詳解
http://www.cnblogs.com/mushroom/p/4231642.html#3760225 Net作業調度(四)—quartz.net持久化和集群
http://www.cnblogs.com/lanxiaoke/p/6629481.html 任務調度之持久化(基於Quartz.net)
http://www.cnblogs.com/lanxiaoke/p/6637714.html 任務調度之集群(基於Quartz.net)
http://www.cnblogs.com/huangxincheng/p/6916246.html 使用sqlserver搭建高可用雙機熱備的Quartz集群部署【附源碼】
這裏博主這裏就不在啰嗦怎麽操作了(上文有仔細操作),直接去做實驗驗證即可,實驗之前先說幾個註意事項:
1、在持久化模式下面,當Scheduler調度器總是執行和線程池相當的任務job數的時候,數據庫連接數盡量要保證是 ThreadPool線程數量+1 的狀態,前提是沒超過最大連接數
2、在集群的情況下,當jobDetail設置為 RequestsRecovery -> true 當前的JobDetail才有效果
3、集群配置:除了線程池數量,instanceId可以不同外,各個節點的配置必須是一樣的
4、集群中節點的系統時間一致
5、註意持久化和集群模式下的配置項

在經過一番測試集群發現,Quartz.Net會自動沖裁不可用的節點,讓一個可用節點來執行,內部有機制去測試每個節點的可用情況會定時去檢測然後剔除,以及新晉節點的加入等,也正好體現了所謂的負載均衡和故障轉移咯,博主測試環境:應用程序Console、數據庫Sql server localdb,本機附帶兩個應用實例測試,發現切換節點時間差為16s...


Quartz.Net UI控制臺

CrystalQuartz : github地址:https://github.com/guryanovev/CrystalQuartz 至於集成方式、方法項目地址當中有說明拉...


總結

哇,不知不覺居然還花了挺多的時間去學習與研究這個框架,先是了解生態圈中的定時器框架比較流行的(當然也包含了Hangfire後面我們有機會也去學習學習),然後想著之前對Quartz有點懵懵懂懂的,所以就去系統的看了看官方文檔了解了解人家的設計思想和實現,到了後面帶著問題去看了些源代碼哈,然後跟著官方的文檔基本擼了一遍之後,包含了去園中也去閱讀了其他博主的相關博客,以及周邊衍生物的 CrystalQuartz UI控制臺界面等等。
最後吶,各位看官老爺覺得還可以的話,您的評論和點贊都是對博主的肯定支持或者斧正!!!哈哈,博主會接著繼續框架學習與研究系列....


Tags: 定時器 或者 框架 定時 文檔 什麽

文章來源:


ads
ads

相關文章
ads

相關文章

ad