读书人

Roller的任务调度设计研讨

发布时间: 2012-07-01 13:15:00 作者: rapoo

Roller的任务调度设计探讨

?

背景

?

以前看过Roller的任务调度,最近需要用到。虽然任务调度这方面的第三方支持包不少,比如quartz,但也不想那么麻烦加入这么重量级的框架。也不知道为什么Roller的设计不用quartz之类的调度框架,也许Roller项目开始的quartz还没有成熟吧。这些就无法去管了,问题是Roller的任务调度如果不是经常使用,很快就忘记了,所以决定以本文记录一下,以后参考。

?

类图

?

?Roller的任务调度设计研讨

TreadManager及其子类主要是初始化任务列表、启动任务调度器TaskScheduler、登记任务租期、解除租期。

?

TaskScheduler:主要管理任务调度,将加到其列表中的任务按照指定时间来启动。

?

RollerTask:定义了一系列的抽象方法,用于任务调度、运行期间操作。

?

RollerTaskWithLeasing: 定义了一个执行具体任务的抽象方法,和实现run方法。主要是为了控制相同的任务不能在同一租期内执行。

?

TaskLock:一个记录任务的相关信息类,提供两个重要的方法:1、计算下次执行时间;2、计算任务执行完毕时间。

工作原理

?

Roller启动后,会初始化所有管理类,JPAThreadManagerImpl也在初始化之列。JPAThreadManagerImpl的initialize被执行,此方法主要的逻辑有:

?

至此,JPAThreadManagerImpl初始化完成,控制权交给任务调度器TaskScheduler。在TaskScheduler的run方法中有个while循环,此循环一直运行到Roller被停止,其主要目的是为了控制在任务列表webloggerTasks中的任务的调度。

?

过程如下:

?

?

由于任务调度器TaskScheduler不断循环,所有加到任务列表里的任务都可能不止一次被启动,那么Roller是如何控制一个任务能被按指定的时间来启动的呢?除了前面的分析,后面还有一个任务的加锁解锁的过程。

?

当RollerTask被放到线程池并且启动后,其抽象子类RollerTaskWithLeasing的run方法将被执行,run方法在这里是一个模板方法。通过前面的分析,我们知道任务调度器TaskScheduler在某个微小时段会多次启动同一个任务,那么如何控制一个已经被启动的任务在它未完成之前,相同的任务不能启动呢?run方法主要是解决这个问题,其主要逻辑是对此任务执行期间加锁,执行结束解锁。

?

当run被执行时:

这里有主要的逻辑要说明,先从数据库将任务的TaskLock信息读取出来,这些信息包括timeAquired(上次被读取的时间)、timeLeased(租期分钟)、最后一次执行时间等。然后通过timeAquired和timeLeased来计算当前时间是否在上次执行租期后面。如果是在后面则表示这次登记租期成功。

?

具体技巧如下,如果能成功执行下面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 < CURRENT_TIMESTAMP</query>

?

?

?

至此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中添加类名。

读书人网 >软件架构设计

热点推荐