Roller的任務調度設計探討

 

背景

 

以前看過Roller的任務調度,最近需要用到。雖然任務調度這方面的第三方支持包不少,比如quartz,但也不想那麼麻煩加入這麼重量級的框架。也不知道爲什麼Roller的設計不用quartz之類的調度框架,也許Roller項目開始的quartz還沒有成熟吧。這些就無法去管了,問題是Roller的任務調度如果不是經常使用,很快就忘記了,所以決定以本文記錄一下,以後參考。

 

類圖

 

 

TreadManager及其子類主要是初始化任務列表、啓動任務調度器TaskScheduler、登記任務租期、解除租期。

 

TaskScheduler:主要管理任務調度,將加到其列表中的任務按照指定時間來啓動。

 

RollerTask:定義了一系列的抽象方法,用於任務調度、運行期間操作。

 

RollerTaskWithLeasing 定義了一個執行具體任務的抽象方法,和實現run方法。主要是爲了控制相同的任務不能在同一租期內執行。

 

TaskLock:一個記錄任務的相關信息類,提供兩個重要的方法:1、計算下次執行時間;2、計算任務執行完畢時間。

工作原理

 

Roller啓動後,會初始化所有管理類,JPAThreadManagerImpl也在初始化之列。JPAThreadManagerImplinitialize被執行,此方法主要的邏輯有:

1、 讀取配置文件,獲得需要實例化的任務RollerTask類的子類,並實例化和初始化這些任務對象。

2、 如果這些任務沒有加鎖TaskLock,則新建一個鎖,並保存到數據庫中。

3、 將任務對象加入到任務列表中webloggerTasks

4、 將任務列表作爲參數,創建一個任務調度器TaskScheduler

5、 將任務調度器TaskScheduler(通過類圖可TaskSchedulerrunnable實現類)作爲參數,創建一個線程並啓動。

 

至此,JPAThreadManagerImpl初始化完成,控制權交給任務調度器TaskScheduler。在TaskSchedulerrun方法中有個while循環,此循環一直運行到Roller被停止,其主要目的是爲了控制在任務列表webloggerTasks中的任務的調度。

 

過程如下:

1、 遍歷所有任務列表中的RollerTask對象。

2、 取得RollerTask的鎖TaskLock(初始化的時候已經加鎖)。

3、 計算下次啓動時間(通過TaskLockRollerTask的相關方法)。

4、 如果下次啓動時間大於當前時間+1分鐘

a)   如果是startOfDay,並且當前時間大於當天000 + 2分鐘,繼續等待;

b)   如果是startOfHour,並且當前時間大於當時00 + 2分鐘,繼續等待;

c)   如果是immediate,下一步。

 

5、 如果當前時間大於等於下次運行時間,並且第4步計算不需要等待,則將RollerTask提交到線程池被啓動。

 

由於任務調度器TaskScheduler不斷循環,所有加到任務列表裏的任務都可能不止一次被啓動,那麼Roller是如何控制一個任務能被按指定的時間來啓動的呢?除了前面的分析,後面還有一個任務的加鎖解鎖的過程。

 

RollerTask被放到線程池並且啓動後,其抽象子類RollerTaskWithLeasingrun方法將被執行,run方法在這裏是一個模板方法。通過前面的分析,我們知道任務調度器TaskScheduler在某個微小時段會多次啓動同一個任務,那麼如何控制一個已經被啓動的任務在它未完成之前,相同的任務不能啓動呢?run方法主要是解決這個問題,其主要邏輯是對此任務執行期間加鎖,執行結束解鎖。

 

run被執行時:

1、 登記租期,表示任務如果被執行,那麼現在開始到什麼時候結束。也就是加鎖的意思,其他相同的任務不能在租期未結束之前執行。

這裏有主要的邏輯要說明,先從數據庫將任務的TaskLock信息讀取出來,這些信息包括timeAquired(上次被讀取的時間)、timeLeased(租期分鐘)、最後一次執行時間等。然後通過timeAquiredtimeLeased來計算當前時間是否在上次執行租期後面。如果是在後面則表示這次登記租期成功。

 

具體技巧如下,如果能成功執行下面sql,表示登記成功。

<query> UPDATE TaskLock t SET t.clientId=?1, t.timeAquired= CURRENT_TIMESTAMP, t.timeLeased= ?2, t.lastRun= ?3 WHERE t.name=?4 AND t.timeAquired=?5 AND ?6 &lt; CURRENT_TIMESTAMP</query>

 

 

2、 如果登記租期成功,執行具體任務。

3、 註銷租期,表示任務已經執行完畢,租期解除。

 

至此Roller任務調度管理整改流程大概是這樣子。

 

注意事項

1、配置說明

# Tasks which are enabled.  Only tasks listed here will be run.

tasks.enabled=ScheduledEntriesTask,ResetHitCountsTask,TurnoverReferersTask,PingQueueTask

 

# client identifier.  should be unique for each instance in a cluster.

tasks.clientId=defaultClientId

 

# Publish scheduled weblog entries

tasks.ScheduledEntriesTask.class=org.apache.roller.weblogger.business.runnable.ScheduledEntriesTask

# 可以設置的值有:'immediate', 'startOfDay', 'startOfHour'

tasks.ScheduledEntriesTask.startTime=immediate   

# 表示兩次任務執行的時間間隔,單位:分鐘

tasks.ScheduledEntriesTask.interval=1

# 表示任務從開始執行到完畢需要的時間,單位:分鐘

tasks.ScheduledEntriesTask.leaseTime=30

 

 

2實現類,建議拷貝RollerTaskWithLeasing的子類來修改即可。同時注意配置是要在tasks.enabled中添加類名。

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