前言
最近一段時間因公司專案需要進行分散式定時任務框架選型,由於資源(人力,時間)有限,所以重點考慮採用開源的一些解決方案,其中重點比較了3款框架:quartz,elastic-job,xxl-job等。由於elastic-job 和xxl-job 實際上也是基於quartz實現的。所以很有必要對quartz 有一定的瞭解。所以近期閱讀了大量quartz相關的一些文件和部落格,以及寫了一些demo進行驗證。本文主要是對近期工作的一個小結,簡要的介紹一下quartz 這個分散式定時任務排程框架。
目錄
- 什麼是quartz?它有哪些特性?
- quartz 核心概念和元素介紹
- quartz 常用配置項介紹
- quartz 叢集介紹
一.什麼是quartz?它有哪些特性?
quartz 是一個開源的分散式排程庫,它基於java實現。
> 它有著強大的排程功能,支援豐富多樣的排程方式,比如簡單排程,基於cron表示式的排程等等。
> 支援排程任務的多種持久化方式。比如支援記憶體儲存,資料庫儲存,Terracotta server 儲存。
> 支援分散式和叢集能力。
> 採用JDBCJobStore方式儲存時,針對事務的處理方式支援全域性事務(和業務服務共享同一個事務)和區域性事務(quarzt 單獨管理自己的事務)
> 基於plugin機制以及listener機制支援靈活的擴充套件。
複製程式碼
二. quartz 核心概念和元素介紹:
-
Job: 工作任務。它提供了一個介面,只有一個方法void execute(JobExecutionContext context),開發者實現該介面定義執行任務,JobExecutionContext類提供了排程上下文的各種資訊。Job執行時的資訊儲存在JobDataMap例項中.
-
JobDetail:工作任務例項.Quartz在每次執行Job時,都重新建立一個Job例項,所以它不直接接受一個Job的例項,相反它接收一個Job實現類,以便執行時通過newInstance()的反射機制例項化Job。因此需要通過一個類來描述Job的實現類及其它相關的靜態資訊,如Job名字、描述、關聯監聽器等資訊,JobDetail承擔了這一角色.
-
Trigger:觸發器,用來描述觸發Job執行的時間觸發規則。主要有SimpleTrigger和CronTrigger這兩個子類。當僅需觸發一次或者以固定時間間隔週期執行,SimpleTrigger是最適合的選擇;而CronTrigger則可以通過Cron表示式定義出各種複雜時間規則的排程方案:如每早晨9:00執行,週一、週三、週五下午5:00執行等.
-
Calendar:日曆,它表示一些特定時間點的集合.一個Trigger可以和多個Calendar關聯,以便排除或包含某些時間點。假設,我們安排每週星期一早上10:00執行任務,但是如果碰到法定的節日,任務則不執行,這時就需要在Trigger觸發機制的基礎上使用Calendar進行定點排除。
-
Scheduler:排程器,代表一個Quartz的獨立執行容器,Trigger和JobDetail可以註冊到Scheduler中,兩者在Scheduler中擁有各自的組及名稱,組及名稱是Scheduler查詢定位容器中某一物件的依據,Trigger的組及名稱必須唯一,JobDetail的組和名稱也必須唯一(但可以和Trigger的組和名稱相同,因為它們是不同型別的)。Scheduler定義了多個介面方法,允許外部通過組及名稱訪問和控制容器中Trigger和JobDetail。
Scheduler可以將Trigger繫結到某一JobDetail中,這樣當Trigger觸發時,對應的Job就被執行。一個Job可以對應多個Trigger,但一個Trigger只能對應一個Job。 複製程式碼
三. quarz 常用配置項介紹
quartz 預設的配置檔案是quartz.properties ,裡面有很多配置項,比如排程器(schedule)相關配置,事務的配置,監聽器,外掛的配置,rmi 相關配置,叢集相關配置等等。 詳細配置資訊可以參照官方文件:www.quartz-scheduler.org/documentati…
四. quratz 叢集介紹
quartz 叢集是依賴於資料庫機制實現的。部署多個節點的quartz 資料庫配置必須保持一致。quartz叢集是通過資料庫表來感知其他的應用的,各個節點之間並沒有直接的通訊。只有使用持久的JobStore才能實現Quartz叢集。
quartz 預設提供了11張資料庫表:
-
QRTZ_CALENDARS: 儲存Quartz的Calendar資訊
-
QRTZ_CRON_TRIGGERS:儲存CronTrigger,包括Cron表示式和時區資訊
-
QRTZ_FIRED_TRIGGERS:儲存與已觸發的Trigger相關的狀態資訊,以及相聯Job的執行資訊
-
QRTZ_PAUSED_TRIGGER_GRPS:儲存已暫停的Trigger組的資訊
-
QRTZ_SCHEDULER_STATE:儲存少量的有關Scheduler的狀態資訊,和別的Scheduler例項
-
QRTZ_LOCKS:儲存程式的悲觀鎖的資訊
-
QRTZ_JOB_DETAILS:儲存每一個已配置的Job的詳細資訊
-
QRTZ_SIMPLE_TRIGGERS:儲存簡單的Trigger,包括重複次數、間隔、以及已觸的次數
-
QRTZ_BLOG_TRIGGERS Trigger作為Blob型別儲存
-
QRTZ_TRIGGERS 儲存已配置的Trigger的資訊
-
QRTZ_SIMPROP_TRIGGERS:儲存簡單觸發器相關。
要注意的是quartz叢集間的相互感知是通過資料庫表(QRTZ_SCHEDULER_STATE)實現的。對於水平叢集,存在著時間同步問題。節點用時間戳來通知其他例項它自己的最後檢入時間。假如節點的時鐘被設定為將來的時間,那麼執行中的Scheduler將再也意識不到那個結點已經宕掉了。另一方面,如果某個節點的時鐘被設定為過去的時間,也許另一節點就會認定那個節點已宕掉並試圖接過它的Job重執行。 複製程式碼
小結
本文只是對quartz 分散式定時任務做了一個簡單的介紹。quartz 作為一個成熟的分散式定時任務框架,然而好像並沒有提供友好的運維管理介面,幸運的是很多的開源框架彌補了這個不足,比如elastic-job ,xxl-job等等,關於quartz 的更多內容,在後面不斷的實踐中再補充。