1、Quartz任務調(diào)度的基本實現(xiàn)原理
Quartz是OpenSymphony開源組織在任務調(diào)度領(lǐng)域的一個開源項目,完全基于Java實現(xiàn)。作為一個優(yōu)秀的開源調(diào)度框架,Quartz具有以下特點:
(1)強大的調(diào)度功能,例如支持豐富多樣的調(diào)度方法,可以滿足各種常規(guī)及特殊需求;
?。?)靈活的應用方式,例如支持任務和調(diào)度的多種組合方式,支持調(diào)度數(shù)據(jù)的多種存儲方式;
?。?)分布式和集群能力,Terracotta收購后在原來功能基礎(chǔ)上作了進一步提升。本文將對該部分相加闡述。
1.1 Quartz 核心元素
Quartz任務調(diào)度的核心元素為:Scheduler——任務調(diào)度器、Trigger——觸發(fā)器、Job——任務。其中trigger和job是任務調(diào)度的元數(shù)據(jù),scheduler是實際執(zhí)行調(diào)度的控制器。
Trigger是用于定義調(diào)度時間的元素,即按照什么時間規(guī)則去執(zhí)行任務。Quartz中主要提供了四種類型的trigger:SimpleTrigger,CronTirgger,DateIntervalTrigger,和NthIncludedDayTrigger。這四種trigger可以滿足企業(yè)應用中的絕大部分需求。
Job用于表示被調(diào)度的任務。主要有兩種類型的job:無狀態(tài)的(stateless)和有狀態(tài)的(stateful)。對于同一個trigger來說,有狀態(tài)的job不能被并行執(zhí)行,只有上一次觸發(fā)的任務被執(zhí)行完之后,才能觸發(fā)下一次執(zhí)行。Job主要有兩種屬性:volatility和durability,其中volatility表示任務是否被持久化到數(shù)據(jù)庫存儲,而durability表示在沒有trigger關(guān)聯(lián)的時候任務是否被保留。兩者都是在值為true的時候任務被持久化或保留。一個job可以被多個trigger關(guān)聯(lián),但是一個trigger只能關(guān)聯(lián)一個job。
Scheduler由scheduler工廠創(chuàng)建:DirectSchedulerFactory或者StdSchedulerFactory。第二種工廠StdSchedulerFactory使用較多,因為DirectSchedulerFactory使用起來不夠方便,需要作許多詳細的手工編碼設(shè)置。Scheduler主要有三種:RemoteMBeanScheduler,RemoteScheduler和StdScheduler。
Quartz核心元素之間的關(guān)系如圖1.1所示:
圖1.1 核心元素關(guān)系圖
1.2 Quartz 線程視圖
在Quartz中,有兩類線程,Scheduler調(diào)度線程和任務執(zhí)行線程,其中任務執(zhí)行線程通常使用一個線程池維護一組線程。
Scheduler調(diào)度線程主要有兩個:執(zhí)行常規(guī)調(diào)度的線程,和執(zhí)行misfiredtrigger的線程。常規(guī)調(diào)度線程輪詢存儲的所有trigger,如果有需要觸發(fā)的trigger,即到達了下一次觸發(fā)的時間,則從任務執(zhí)行線程池獲取一個空閑線程,執(zhí)行與該trigger關(guān)聯(lián)的任務。Misfire線程是掃描所有的trigger,查看是否有misfiredtrigger,如果有的話根據(jù)misfire的策略分別處理(fire now OR wait for the next fire)。
1.3 Quartz Job數(shù)據(jù)存儲
Quartz中的trigger和job需要存儲下來才能被使用。Quartz中有兩種存儲方式:RAMJobStore,JobStoreSupport,其中RAMJobStore是將trigger和job存儲在內(nèi)存中,而JobStoreSupport是基于jdbc將trigger和job存儲到數(shù)據(jù)庫中。RAMJobStore的存取速度非???,但是由于其在系統(tǒng)被停止后所有的數(shù)據(jù)都會丟失,所以在集群應用中,必須使用JobStoreSupport。
2、Quartz集群原理2.1 Quartz 集群架構(gòu)
一個Quartz集群中的每個節(jié)點是一個獨立的Quartz應用,它又管理著其他的節(jié)點。這就意味著你必須對每個節(jié)點分別啟動或停止。Quartz集群中,獨立的Quartz節(jié)點并不與另一其的節(jié)點或是管理節(jié)點通信,而是通過相同的數(shù)據(jù)庫表來感知到另一Quartz應用的,如圖2.1所示。
2.2 Quartz集群相關(guān)數(shù)據(jù)庫表
因為Quartz集群依賴于數(shù)據(jù)庫,所以必須首先創(chuàng)建Quartz數(shù)據(jù)庫表,Quartz發(fā)布包中包括了所有被支持的數(shù)據(jù)庫平臺的SQL腳本。這些SQL腳本存放于<quartz_home>/docs/dbTables 目錄下。這里采用的Quartz 1.8.4版本,總共12張表,不同版本,表個數(shù)可能不同。數(shù)據(jù)庫為mysql,用tables_mysql.sql創(chuàng)建數(shù)據(jù)庫表。全部表如圖2.2所示,對這些表的簡要介紹如圖2.3所示。
2.2.1 調(diào)度器狀態(tài)表(QRTZ_SCHEDULER_STATE)
說明:集群中節(jié)點實例信息,Quartz定時讀取該表的信息判斷集群中每個實例的當前狀態(tài)。
instance_name:配置文件中org.quartz.scheduler.instanceId配置的名字,如果設(shè)置為AUTO,quartz會根據(jù)物理機名和當前時間產(chǎn)生一個名字。
last_checkin_time:上次檢入時間
checkin_interval:檢入間隔時間
2.2.2 觸發(fā)器與任務關(guān)聯(lián)表(qrtz_fired_triggers)
存儲與已觸發(fā)的Trigger相關(guān)的狀態(tài)信息,以及相聯(lián)Job的執(zhí)行信息。
2.2.3 觸發(fā)器信息表(qrtz_triggers)
trigger_name:trigger的名字,該名字用戶自己可以隨意定制,無強行要求
trigger_group:trigger所屬組的名字,該名字用戶自己隨意定制,無強行要求
job_name:qrtz_job_details表job_name的外鍵
job_group:qrtz_job_details表job_group的外鍵
trigger_state:當前trigger狀態(tài)設(shè)置為ACQUIRED,如果設(shè)為WAITING,則job不會觸發(fā)
trigger_cron:觸發(fā)器類型,使用cron表達式
2.2.4 任務詳細信息表(qrtz_job_details)
說明:保存job詳細信息,該表需要用戶根據(jù)實際情況初始化
job_name:集群中job的名字,該名字用戶自己可以隨意定制,無強行要求。
job_group:集群中job的所屬組的名字,該名字用戶自己隨意定制,無強行要求。
job_class_name:集群中job實現(xiàn)類的完全包名,quartz就是根據(jù)這個路徑到classpath找到該job類的。
is_durable:是否持久化,把該屬性設(shè)置為1,quartz會把job持久化到數(shù)據(jù)庫中
job_data:一個blob字段,存放持久化job對象。
2.2.5權(quán)限信息表(qrtz_locks)
說明:tables_oracle.sql里有相應的dml初始化,如圖2.4所示。
2.3 Quartz Scheduler在集群中的啟動流程
Quartz Scheduler自身是察覺不到被集群的,只有配置給Scheduler的JDBC JobStore才知道。當Quartz Scheduler啟動時,它調(diào)用JobStore的schedulerStarted()方法,它告訴JobStore Scheduler已經(jīng)啟動了。schedulerStarted() 方法是在JobStoreSupport類中實現(xiàn)的。JobStoreSupport類會根據(jù)quartz.properties文件中的設(shè)置來確定Scheduler實例是否參與到集群中。假如配置了集群,一個新的ClusterManager類的實例就被創(chuàng)建、初始化并啟動。ClusterManager是在JobStoreSupport類中的一個內(nèi)嵌類,繼承了java.lang.Thread,它會定期運行,并對Scheduler實例執(zhí)行檢入的功能。Scheduler也要查看是否有任何一個別的集群節(jié)點失敗了。檢入操作執(zhí)行周期在quartz.properties中配置。
2.4 偵測失敗的Scheduler節(jié)點
當一個Scheduler實例執(zhí)行檢入時,它會查看是否有其他的Scheduler實例在到達他們所預期的時間還未檢入。這是通過檢查SCHEDULER_STATE表中Scheduler記錄在LAST_CHEDK_TIME列的值是否早于org.quartz.jobStore.clusterCheckinInterval來確定的。如果一個或多個節(jié)點到了預定時間還沒有檢入,那么運行中的Scheduler就假定它(們) 失敗了。
2.5 從故障實例中恢復Job
當一個Sheduler實例在執(zhí)行某個Job時失敗了,有可能由另一正常工作的Scheduler實例接過這個Job重新運行。要實現(xiàn)這種行為,配置給JobDetail對象的Job可恢復屬性必須設(shè)置為true(job.setRequestsRecovery(true))。如果可恢復屬性被設(shè)置為false(默認為false),當某個Scheduler在運行該job失敗時,它將不會重新運行;而是由另一個Scheduler實例在下一次觸發(fā)時間觸發(fā)。Scheduler實例出現(xiàn)故障后多快能被偵測到取決于每個Scheduler的檢入間隔(即2.3中提到的org.quartz.jobStore.clusterCheckinInterval)。
3、Quartz集群實例(Quartz+Spring)
3.1 Spring不兼容Quartz問題
Spring從2.0.2開始便不再支持Quartz。具體表現(xiàn)在Quartz+Spring把Quartz的Task實例化進入數(shù)據(jù)庫時,會產(chǎn)生:Serializable的錯誤:
<bean id="jobtask" class="org.springframework.scheduling.quartz. MethodInvokingJobDetailFactoryBean "> <property name="targetObject"> <ref bean="quartzJob"/> </property> <property name="targetMethod"> <value>execute</value> </property> </bean>
新聞名稱:Quartz集群原理以及配置應用的方法詳解-創(chuàng)新互聯(lián)
網(wǎng)頁地址:http://jinyejixie.com/article30/hiiso.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供標簽優(yōu)化、定制開發(fā)、網(wǎng)站建設(shè)、全網(wǎng)營銷推廣、移動網(wǎng)站建設(shè)、企業(yè)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容