分布式任務調度——quartz + spring + 數據庫


    項目中使用分布式並發部署定時任務,多台跨JVM,按照常理邏輯每個JVM的定時任務會各自運行,這樣就會存在問題,多台分布式JVM機器的應用服務同時干活,一個是加重服務負擔,另外一個是存在嚴重的邏輯問題,比如需要回滾的數據,就回滾了多次,剛好quartz提供很好的解決方案。
    集群分布式並發環境中使用QUARTZ定時任務調度,會在各個節點會上報任務,存到數據庫中,執行時會從數據庫中取出觸發器來執行,如果觸發器的名稱和執行時間相同,則只有一個節點去執行此任務。 
    如果此節點執行失敗,則此任務則會被分派到另一節點執行,中途也會自動檢查失效的定時調度,發現不成功的,其他節點立馬接過來繼續完成定時任務。對應的定時任務調度表比較多,有11個。
 
后續功能
    准備code一個web調度工作台,對所有job進行統計管理和監控;
 
引入依賴:
<!-- quartz -->
<dependency>
        <groupId>org.quartz-scheduler</groupId>
        <artifactId>quartz</artifactId>
        <version>2.2.1</version>
</dependency>
 
配置quartz數據庫
    官網下載,tz壓縮包,在解壓目錄docs\dbTables下找到對應的執行sql,執行即可;
 
配置本地quartz.properties
    單機版,使用RAMJobStore存儲任務,可以使用jar包總默認配置,改方式執行最迅速,強大,方便;
    集群版本,需要copy出jar包中配置,新增如下配置,並注釋掉重復配置項目,即可;
        # for cluster
        org.quartz.scheduler.instanceId: AUTO
        org.quartz.jobStore.class: org.quartz.impl.jdbcjobstore.JobStoreTX
        org.quartz.jobStore.isClustered: true
        org.quartz.jobStore.clusterCheckinInterval: 1000
 
創建CronTrigger和JobDetail,二者為包含關系
Quartz2.0創建JobDetail有兩種方式:
方式一:CronTrigger包含JobDetail,JobDetail用MethodInvokingJobDetailFactoryBean工廠Bean包裝普通的Java對象或bean;
<!-- Job trigger -->
<bean id="job01Trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
      <property name="jobDetail" >
           <bean class="org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean">
                <property name="targetObject" ref="jobService" />
                <property name="targetMethod" value="job01" />
                <property name="concurrent" value="false" />
           </bean>
      </property>
      <property name="cronExpression" value="0/3 * * * * ? *" />
 </bean>
方式二:CronTrigger包含JobDetail,JobDetail用JobDetailFactoryBean包裝QuartzJobBean的繼承子類(即Job類)的實例;
    <!-- Job trigger -->
    <bean id="job02Trigger" class="org.springframework.scheduling.quartz.CronTriggerFactoryBean">
        <property name="jobDetail" >
            <bean class="org.springframework.scheduling.quartz.JobDetailFactoryBean">
                <property name="jobClass" value="com.xxl.job.JobDetailDemo"/>
                <property name="jobDataAsMap">
                    <map>
                        <!-- <entry key="xxService" value-ref="xxService" /> -->
                    </map>
                </property>  
                <property name="durability" value="true"></property>
            </bean>
        </property>
        <property name="cronExpression" value="0/1 * * * * ? *" />
    </bean>
 
創建調度工廠,根據數據存儲方式,分為兩種
方式一:內存RAMJobStore:把job的相關信息存儲在內存里,如果用spring配置quartz的job信息的話,所有信息是配置在xml里,當spirng context啟動的時候就把xml里的job信息裝入內存。
<bean name="startQuertz" lazy-init="false" autowire="no" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">
      <property name="triggers">
           <list>
                <ref bean="job01Trigger" />
           </list>
      </property>
 </bean>
方式二:數據庫:讀取配置在數據庫里的job初始化信息,並且把job通過java序列化到數據庫里,這樣就使得每個job信息得到了持久化,即使在jvm或者容器掛掉的情況下,也能通過數據庫感知到其他job的狀態和信息;quartz集群各節點之間是通過同一個數據庫實例(准確的說是同一個數據庫實例的同一套表)來感知彼此的。 
<bean id="quartzScheduler" lazy-init="false" class="org.springframework.scheduling.quartz.SchedulerFactoryBean"> 
      <property name="dataSource" ref="dataSource" />
      <property name="autoStartup" value="true" />
      <property name="applicationContextSchedulerContextKey"  value="applicationContextKey" />
       <property name="configLocation" value="classpath:quartz.properties"/>
      <property name="triggers">
           <list>
                <ref bean="job02Trigger" />
           </list>
      </property>
 </bean>
 
tips:applicationContextSchedulerContextKey: 是org.springframework.scheduling.quartz.SchedulerFactoryBean這個類中把spring上下 文以key/value的方式存放在了quartz的上下文中了,可以用applicationContextSchedulerContextKey所定義的key得到對應的spring上下文。
 
實例應用
.. quartz-demo.zip..
 
 
 
 
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM