詳細講解Quartz

Quartz是一個開源的作業調度框架,它完全由Java寫成,並設計用於J2SE和J2EE應用中。它提供了巨大的靈活性而不犧牲簡單性。你能夠用它來爲執行一個作業而創建簡單的或複雜的調度。它有很多特徵,如:數據庫支持,集羣,插件,EJB作業預構建,JavaMail及其它,支持cron-like表達式等等。

本文內容

1、Quartz讓任務調度簡單

2、Quartz的發展史

3、上手Quartz

4、Quartz內部架構

5、作業

6、作業管理和存儲

7、有效作業存儲

8、作業和觸發器

9、調度一個作業

10、用調度器(Scheduler)調用你的作業

11、編程調度同聲明性調度

12、有狀態和無狀態作業

13、Quartz框架的其他特徵

14、Quartz下一步計劃

15、瞭解更多Quartz特徵

你曾經需要應用執行一個任務嗎?這個任務每天或每週星期二晚上11:30,或許僅僅每個月的最後一天執行。一個自動執行而無須干預的任務在執行過程中如果發生一個嚴重錯誤,應用能夠知到其執行失敗並嘗試重新執行嗎?你和你的團隊是用Java編程嗎?如果這些問題中任何一個你回答是,那麼你應該使用Quartz調度器。

旁註:Matrix目前就大量使用到了Quartz。比如,排名統計功能的實現,在Jmatrix裏通過Quartz定義了一個定時調度作業,在每天凌晨一點,作業開始工作,重新統計大家的Karma和排名等。

還有,RSS文件的生成,也是通過Quartz定義作業,每隔半個小時生成一次RSS XML文件。

所以Quartz使用的地方很多,本文無疑是一篇很好的入門和進階的文章,在此,感謝David w Johnson的努力!

Quartz讓作業調度簡單

Quartz是一個完全由Java編寫的開源作業調度框架。不要讓作業調度這個術語嚇着你。儘管Quartz框架整合了許多額外功能,但就其簡易形式看,你會發現它易用得簡直讓人受不了!。簡單地創建一個實現org.quartz.Job接口的Java類。Job接口包含唯一的方法:

在你的Job接口實現類裏面,添加一些邏輯到execute()方法。一旦你配置好Job實現類並設定好調度時間表,Quartz將密切注意剩餘時間。當調度程序確定該是通知你的作業的時候,Quartz框架將調用你Job實現類(作業類)上的execute()方法並允許做它該做的事情。無需報告任何東西給調度器或調用任何特定的東西。僅僅執行任務和結束任務即可。如果配置你的作業在隨後再次被調用,Quartz框架將在恰當的時間再次調用它。

如果你使用了其它流行的開源框架象struts,你會對Quartz的設計和部件感到舒適。雖然兩個開源工程是解決完全不同的問題,還是有很多相似的之處,就是開源軟件用戶每天感覺很舒適。Quartz能用在單機J2SE應用中,作爲一個RMI服務器,也可以用在web應用中,甚至也可以用在J2EE應用服務器中。

Quartz的發展史

儘管Quartz今年開始受到人們注意,但還是暫時流行。Quartz由James House創建並最初於2001年春天被加入sourceforge工程。接下來的幾年裏,有許多新特徵和版本出現,但是直到項目遷移到新的站點併成爲OpenSymphony項目家族的一員,纔開始真正啓動並受到應有的關注。

James House仍然和幾個協助他的業餘開發者參與大量開發工作。Quartz開發團隊今年能發佈幾個新版本,包括當前正處在候選發佈階段的1.5版。

上手Quartz

Quartz工程駐留在OpenSymphony站點上。在Quartz站點上可以找到許多有用的資源:JavaDocs,包含指南的文檔,CVS訪問,用戶和開發者論壇的連接,當然也有下載。

從下載連接取得Quartz的發佈版本,並且解壓到到本地目錄。這個下載文件包含了一個預先構建好的Quartz二進制文件(quartz.jar),你可以將它放進自己的應用中。Quartz框架只需要少數的第三方庫,並且這些三方庫是必需的,你很可能已經在使用這些庫了。

你要把Quartz的安裝目錄的/lib/core 和 /lib/optional目錄中的第三方庫加進你自己的工程中。大多數第三方庫是我們所熟知和喜歡的標準Jakarta Commons庫,像Commons Logging, Commons BeantUtils等等。

quartz.properties文件

Quartz有一個叫做quartz.properties的配置文件,它允許你修改框架運行時環境。缺省是使用Quartz.jar裏面的quartz.properties文件。當然,你應該創建一個quartz.properties文件的副本並且把它放入你工程的classes目錄中以便類裝載器找到它。quartz.properties樣本文件如例1所示。

例1.quartz.properties文件允許修改Quartz運行環境:

一旦將Quartz.jar文件和第三方庫加到自己的工程裏面並且quartz.properties文件在工程的classes目錄中,就可以創建作業了。然而,在做這之前,我們暫且迴避一下先簡短討論一下Quartz架構。

Quartz內部架構

在規模方面,Quartz跟大多數開源框架類似。大約有300個Java類和接口,並被組織到12個包中。這可以和Apache Struts把大約325個類和接口以及組織到11個包中相比。儘管規模幾乎不會用來作爲衡量框架質量的一個特性,但這裏的關鍵是quarts內含很多功能,這些功能和特性集是否成爲、或者應該成爲評判一個開源或非開源框架質量的因素。

Quartz調度器

Quartz框架的核心是調度器。調度器負責管理Quartz應用運行時環境。調度器不是靠自己做所有的工作,而是依賴框架內一些非常重要的部件。Quartz不僅僅是線程和線程管理。爲確保可伸縮性,Quartz採用了基於多線程的架構。

啓動時,框架初始化一套worker線程,這套線程被調度器用來執行預定的作業。這就是Quartz怎樣能併發運行多個作業的原理。Quartz依賴一套鬆耦合的線程池管理部件來管理線程環境。本文中,我們會多次提到線程池管理,但Quartz裏面的每個對象是可配置的或者是可定製的。所以,例如,如果你想要插進自己線程池管理設施,我猜你一定能!

作業

用Quartz的行話講,作業是一個執行任務的簡單Java類。任務可以是任何Java代碼。只需你實現org.quartz.Job接口並且在出現嚴重錯誤情況下拋出JobExecutionException異常即可。

Job接口包含唯一的一個方法execute(),作業從這裏開始執行。一旦實現了Job接口和execute()方法,當Quartz確定該是作業運行的時候,它將調用你的作業。Execute()方法內就完全是你要做的事情。下面有一些你要在作業裏面做事情的例子:

· 用JavaMail(或者用其他的像Commons Net一樣的郵件框架)發送郵件

· 創建遠程接口並且調用在EJB上的方法

· 獲取Hibernate Session,查詢和更新關係數據庫裏的數據

· 使用OSWorkflow並且從作業調用一個工作流

· 使用FTP和到處移動文件

· 調用Ant構建腳本開始預定構建

這種可能性是無窮的,正事這種無限可能性使得框架功能如此強大。Quartz給你提供了一個機制來建立具有不同粒度的、可重複的調度表,於是,你只需創建一個Java類,這個類被調用而執行任務。

作業管理和存儲

作業一旦被調度,調度器需要記住並且跟蹤作業和它們的執行次數。如果你的作業是30分鐘後或每30秒調用,這不是很有用。事實上,作業執行需要非常準確和即時調用在被調度作業上的execute()方法。Quartz通過一個稱之爲作業存儲(JobStore)的概念來做作業存儲和管理。

有效作業存儲

Quartz提供兩種基本作業存儲類型。第一種類型叫做RAMJobStore,它利用通常的內存來持久化調度程序信息。這種作業存儲類型最容易配置、構造和運行。對許多應用來說,這種作業存儲已經足夠了。

然而,因爲調度程序信息是存儲在被分配給JVM的內存裏面,所以,當應用程序停止運行時,所有調度信息將被丟失。如果你需要在重新啓動之間持久化調度信息,則將需要第二種類型的作業存儲。

第二種類型的作業存儲實際上提供兩種不同的實現,但兩種實現一般都稱爲JDBC作業存儲。兩種JDBC作業存儲都需要JDBC驅動程序和後臺數據庫來持久化調度程序信息。這兩種類型的不同在於你是否想要控制數據庫事務或這釋放控制給應用服務器例如BEA's WebLogic或Jboss。(這類似於J2EE領域中,Bean管理的事務和和容器管理事務之間的區別)這兩種JDBC作業存儲是:

· JobStoreTX:當你想要控制事務或工作在非應用服務器環境中是使用

· JobStoreCMT:當你工作在應用服務器環境中和想要容器控制事務時使用。

JDBC作業存儲爲需要調度程序維護調度信息的用戶而設計。

作業和觸發器

Quartz設計者做了一個設計選擇來從調度分離開作業。Quartz中的觸發器用來告訴調度程序作業什麼時候觸發。框架提供了一把觸發器類型,但兩個最常用的是SimpleTrigger和CronTrigger。SimpleTrigger爲需要簡單打火調度而設計。

典型地,如果你需要在給定的時間和重複次數或者兩次打火之間等待的秒數打火一個作業,那麼SimpleTrigger適合你。另一方面,如果你有許多複雜的作業調度,那麼或許需要CronTrigger。

CronTrigger是基於Calendar-like調度的。當你需要在除星期六和星期天外的每天上午10點半執行作業時,那麼應該使用CronTrigger。正如它的名字所暗示的那樣,CronTrigger是基於Unix克隆表達式的。

作爲一個例子,下面的Quartz克隆表達式將在星期一到星期五的每天上午10點15分執行一個作業。

0 15 10 ? * MON-FRI

下面的表達式

0 15 10 ? * 6L 2002-2005

將在2002年到2005年的每個月的最後一個星期五上午10點15分執行作業。你不可能用SimpleTrigger來做這些事情。你可以用兩者之中的任何一個,但哪個跟合適則取決於你的調度需要。

調度一個作業

讓我們通過看一個例子來進入實際討論。現假定你管理一個部門,無論何時候客戶在它的FTP服務器上存儲一個文件,都得用電子郵件通知它。我們的作業將用FTP登陸到遠程服務器並下載所有找到的文件。

然後,它將發送一封含有找到和下載的文件數量的電子郵件。這個作業很容易就幫助人們整天從手工執行這個任務中解脫出來,甚至連晚上都無須考慮。我們可以設置作業循環不斷地每60秒檢查一次,而且工作在7×24模式下。這就是Quartz框架完全的用途。

首先創建一個Job類,將執行FTP和Email邏輯。下例展示了Quartz的Job類,它實現了org.quartz.Job接口。

例2.從FTP站點下載文件和發送email的Quartz作業

我們故意讓ScanFTPSiteJob保持很簡單。我們爲這個例子創建了一個叫做JobUtil的實用類。它不是Quartz的組成部分,但對構建各種作業能重用的實用程序庫來說是有意義的。我們可以輕易將那種代碼組織進作業類中,quarts 調度器一樣好用,因爲我們一直在使用quarts,所以那些代碼可繼續重用。

JobUtil.checkForFiles() and JobUtil.sendEmail()方法使用的參數是Quartz創建的JobDataMap的實例。實例爲每個作業的執行而創建,它是向作業類傳遞配置參數的方法。

這裏並沒有展示JobUtil的實現,但我們能用Jakarta上的Commons Net輕易地實現FTP和Email功能。

用調度器調用作業

首先創建一個作業,但爲使作業能被調度器調用,你得向調度程序說明你的作業的調用時間和頻率。這個事情由與作業相關的觸發器來完成。因爲我們僅僅對大約每60秒循環調用作業感興趣,所以打算使用SimpleTrigger。

作業和觸發器通過Quartz調度器接口而被調度。我們需要從調度器工廠類取得一個調度器的實例。最容易的辦法是調用StdSchedulerFactory這個類上的靜態方法getDefaultScheduler()。

使用Quartz框架,你需要調用start()方法來啓動調度器。例3的代碼遵循了大多數Quartz應用的一般模式:創建一個或多個作業,創建和設置觸發器,用調度器調度作業和觸發器,啓動調度器。

例3.Quartz作業通過Quartz調度器而被調度


編程調度同聲明性調度

例3中,我們通過編程的方法調度我們的ScanFTPSiteJob作業。就是說,我們用Java代碼來設置作業和觸發器。Quartz框架也支持在xml文件裏面申明性的設置作業調度。申明性方法允許我們更快速地修改哪個作業什麼時候被執行。

Quartz框架有一個插件,這個插件負責讀取xml配置文件。xml配置文件包含了關於啓動Quartz應用的作業和觸發器信息。所有xml文件中的作業連同相關的觸發器都被加進調度器。你仍然需要編寫作業類,但配置那些作業類的調度器則非常動態化。例4展示了一個用申明性方式執行與例3代碼相同的邏輯的xml配置文件。

例4.能使用xml文件調度的作業

你可以將xml文件中的元素跟例3代碼作個比較,它們從概念上來看是相同的。使用例4式的申明性方法的好處是維護變得極其簡單,只需改變xml配置文件和重新啓動Quartz應用即可。無須修改代碼,無須重新編譯,無須重新部署。

有狀態和無狀態作業

在本文中你所看到的作業到是無狀態的。這意味着在兩次作業執行之間,不會去維護作業執行時JobDataMap的狀態改變。如果你需要能增、刪,改JobDataMap的值,而且能讓作業在下次執行時能看到這個狀態改變,則需要用Quartz有狀態作業。

如果你是一個有經驗的EJB開發者的話,深信你會立即退縮,因爲有狀態帶有負面含義。這主要是由於EJB帶來的伸縮性問題。Quartz有狀態作業實現了org.quartz.StatefulJob接口。

無狀態和有狀態作業的關鍵不同是有狀態作業在每次執行時只有一個實例。大多數情況下,有狀態的作業不迴帶來大的問題。然而,如果你有一個需要頻繁執行的作業或者需要很長時間才能完成的作業,那麼有狀態作業可能給你帶來伸縮性問題。

Quartz框架的其他特徵

Quartz框架有一個豐富的特徵集。事實上,quarts有太多特性以致不能在一種情況中全部領會,下面列出了一些有意思的特徵,但沒時間在此詳細討論。

監聽器和插件

每個人都喜歡監聽和插件。今天,幾乎下載任何開源框架,你必定會發現支持這兩個概念。監聽是你創建的Java類,當關鍵事件發生時會收到框架的回調。例如,當一個作業被調度、沒有調度或觸發器終止和不再打火時,這些都可以通過設置來來通知你的監聽器。Quartz框架包含了調度器監聽、作業和觸發器監聽。你可以配置作業和觸發器監聽爲全局監聽或者是特定於作業和觸發器的監聽。

一旦你的一個具體監聽被調用,你就能使用這個技術來做一些你想要在監聽類裏面做的事情。例如,你如果想要在每次作業完成時發送一個電子郵件,你可以將這個邏輯寫進作業裏面,也可以JobListener裏面。寫進JobListener的方式強制使用鬆耦合有利於設計上做到更好。

Quartz插件是一個新的功能特性,無須修改Quartz源碼便可被創建和添加進Quartz框架。他爲想要擴展Quartz框架又沒有時間提交改變給Quartz開發團隊和等待新版本的開發人員而設計。如果你熟悉Struts插件的話,那麼完全可以理解Quartz插件的使用。

與其Quartz提供一個不能滿足你需要的有限擴展點,還不如通過使用插件來擁有可修整的擴展點。

集羣Quartz應用

Quartz應用能被集羣,是水平集羣還是垂直集羣取決於你自己的需要。集羣提供以下好處:

· 伸縮性

· 搞可用性

· 負載均衡

目前,Quartz只能藉助關係數據庫和JDBC作業存儲支持集羣。將來的版本這個制約將消失並且用RAMJobStore集羣將是可能的而且將不需要數據庫的支持。

Quartz web應用

使用框架幾個星期或幾個月後,Quartz用戶所顯示的需求之一是需要集成Quartz到圖形用戶界面中。目前Quartz框架已經有一些工具允許你使用Java servlet來初始化和啓動Quartz。一旦你可以訪問調度器實例,你就可以把它存儲在web容器的servlet上下文中(ServletContext中)並且可以通過調度器接口管理調度環境。

幸運的是一些開發者已正影響着單機Quartz web應用,它用來更好地管理調度器環境。構建在若干個流行開源框架如Struts和Spring之上的圖形用戶界面支持很多功能,這些功能都被包裝進一個簡單接口。GUI的一個畫面如圖1所示:

圖1.Quartz Web應用允許比較容易地管理Quartz環境

Quartz的下一步計劃

Quartz是一個活動中的工程。Quartz開發團隊明確表示不會停留在已有的榮譽上。Quartz下一個主要版本已經在啓動中。你可以在OpenSymphony的 wiki上體驗一下Quartz 2.0的設計和特徵。總之,Quartz用戶每天都自由地添加特性建議和設計創意以便能被核心框架考慮(看重)。

瞭解更多Quartz特徵

當你開始使用Quartz框架的更多特性時,User and Developer Forum論壇變成一個回答問題和跟其他Quartz用戶溝通的極其有用的資源。經常去逛逛這個論壇時很有好處的,你也可以依靠James House來共享與你的需要相關的知識和意見。

(T117)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章