Spring+Quartz 集羣

這幾天給Spring+Quartz的集羣折騰得死去活來,google了無數頁總算搞定,記下一些要點備之後使用。

單獨的Quartz集羣在http://unmi.blogjava.net/有Unmi翻譯的Quartz Job Scheduling Framework一書作了詳細說明,在此再也不重複。

Spring+Quartz不集羣的方式google百度也能夠搜索出來一大堆,一樣略過。

要點1 在Spring中使用Quartz的高級配置
問題描述 Quartz集羣僅能使用JDBC JobStore工做,須要在Spring中使用Quartz的高級配置
解決辦法1.1 經過SchedulerFactoryBean的configLocation屬性指定Quartz配置文件的位置。 java

Xml代碼   收藏代碼
  1. <bean id="quartzJobFactory" class="org.springframework.scheduling.quartz.SchedulerFactoryBean">  
  2.     <property name="triggers">  
  3.         <list>  
  4.             <ref bean="clusterTesterJobScheduledTask" />  
  5.         </list>  
  6.     </property>  
  7.     <property name="configLocation" value="classpath:quartz.properties" />  
  8. </bean>  


解決辦法1.2 經過SchedulerFactoryBean的quartzProperties屬性直接配置。

要點2 NotSerializableException
問題描述 在將Quartz的Job持久化到數據庫的過程當中產生NotSerializableException。詳細異常信息爲:
java.io.NotSerializableException: Unable to serialize JobDataMap for insertion into database because the value of property 'methodInvoker' is not serializable: org.springframework.scheduling.quartz.MethodInvokingJobDetailFactoryBean
解決辦法 這是Spring的一個Bug,具體解決方案見http://jira.springframework.org/browse/SPR-3797,上面有解決的MethodInvokingJobDetailFactoryBean代碼。

要點3 仍是NotSerializableException
問題描述 雖然MethodInvokingJobDetailFactoryBean的問題解決了,可是QuartzJob或者QuartzJob的屬性沒有實現Serializable接口(好比在QuartzJob中注入了DAO)。
解決辦法3.1 若是是本身能夠掌握的代碼,能夠爲這些QuartzJob及其屬性都加上實現Serializable接口。
解決辦法3.2 編寫一個實現Serializable接口,沒有屬性的QuartzJob,讓它從Spring容器(ApplicationContext)中獲取原來 的那個QuartzJob的Bean,再調用原來QuartzJob的方法解決問題。該方法的問題在於怎麼獲取ApplicationContext,如 果用ClassPathXmlApplicationContext,等因而另外建立了一個Spring容器(web.xml裏面定義的是另一個)。
解決辦法3.3 將原有的接口暴露,在Job中想辦法遠程調用該接口。
這三種辦法各有好壞,如今也想不出其餘更好的辦法,先用這些頂着吧。

要點4 集羣以後把其中一個Quartz服務停了,其餘的也不接手工做
問題描述 集羣以後,A節點執行了大多數任務,B節點大部分時間處於空閒,停掉A節點,B節點也不會接手工做。
解決辦法 修改Quartz的配置,將每一個節點的org.quartz.scheduler.instanceId設置爲不一樣的值,或者都設置爲AUTO。另外 org.quartz.jobStore.isClustered屬性必須設爲 true,org.quartz.jobStore.clusterCheckinInterval屬性爲集羣中每次檢查的時間間隔(按個人理解,應該差 很少等於一個服務器掛了以後,其餘服務器接手的時間),單位爲毫秒,默認值是15000。

要點5 MethodInvokingJobDetailFactoryBean幾個屬性的做用
問題描述 MethodInvokingJobDetailFactoryBean中concurrent和shouldRecover屬性的做用
解釋 concurrent爲true,則容許一個QuartzJob併發執行,不然就是順序執行。例如QuartzJob A執行時間爲15秒,配置爲每10秒執行一次;若是concurrent爲true,則0秒的時候啓動一次A,10秒的時候再啓動一次A,20秒的時候再 啓動一次A,無論前面啓動的A有沒有執行完;若是concurrent爲false,則0秒的時候啓動一次A,15秒的時候A執行完畢,再第二次啓動A。
shouldRecover屬性爲true,則當Quartz服務被停止後,再次啓動或集羣中其餘機器接手任務時會嘗試恢復執行以前未完成的全部 任務。例如QuartzJob B,在每次00秒的時候啓動,假如在03:00的任務執行完以後服務器1被停止,服務器2在05:15的時候才接手;若是shouldRecover屬性 爲true,則服務器2會嘗試着補回原來在04:00和05:00的時候應該作的任務,若是shouldRecover屬性爲false,則服務器2只會 從06:00的時候再執行B。

附件是一個Demo,使用數據庫爲Oracle,建立數據庫表的SQL腳本能夠在Quartz的發行包(http://www.opensymphony.com/quartz/download.action)中\docs\dbTables目錄下找到。數據庫相關配置都在quartz.properties中,可根據實際須要自行修改。web

相關文章
相關標籤/搜索