Quartz是由三個元件:Scheduler、Trigger和Job組成,一個Job可被多個Trigger使用,一個Trigger可以觸發多個Job,這而實際都是由Scheduler去執行Job的內容。本案是使用賽門奧客的Veritas進行software的failover,因此當failover一切過去,可能未執行、執行中或執行畢的Job都有遇到不同的狀況,因為Vertias是使用Linux上的kill -9指令中止process的。好在Listener的機制這時可以派上用場。Listener也依Quartz三個核心元件而分別對映到這三個Listener,目前以JobListener作飯粒:

(FooJobListener.java)

import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobListener;

public class FooJobListener implements JobListener {
    public void jobExecutionVetoed(JobExecutionContext context) {
        // 被Trigger所阻, Job無法執行
    }

    public void jobToBeExecuted(JobExecutionContext context) {
        // Job執行前
    }

    public void jobWasExecuted(JobExecutionContext context,    JobExecutionException exception) {
        // Job執行後, 失敗的話exception會有值
    }

    public FooJobListener() {
        // 初始化, 在failover切過來後, Quartz被執行可喚起
    }
}

  假設Foo這個Job預定12點在A機執行,但在12:05就被切換到B機,而這時的A機的Foo Job尚未完成,也就是還沒執行到jobWasExecuted method。若要恢復執行前的狀態,即jobToBeExecuted method的內容,這時failover一切過去時,JobListener的建構子內容可以是jobToBeExecuted method的內容,馬上就被執行,不用苦俟到下一個12點去call jobToBeExecuted method來reset。

  而在Scheduler註冊方式如下:

Scheduler scheduler = (new StdSchedulerFactory()).getScheduler();
job = new JobDetail(...);                           // 引數略
JobListener jobListener = new FooJobListener();
scheduler.addJobListener(jobListener);
job.addJobListener(jobListener.getName());
   // Job的addJobListener必須是Listener的name string,如此才會匹配到對映的Job
Trigger trigger = new CronTrigger(...);        // 引數略
scheduler.scheduleJob(job, trigger);
scheduler.start();

  若希望這個Listener通用於所有Job,則用scheduler.addGlobalJobListener(jobListener)取代以上劃有底線的兩行。

  另外兩個Listener的method也加以說明:

public void triggerFired(Trigger trigger, JobExecutionContext context);  // Job 上的 execute() 方法即將被執行時
public boolean vetoJobExecution(Trigger trigger, JobExecutidonContext context); // 返回false則表示這個Listener拒絕執行job
public void triggerMisfired(Trigger trigger);   // 這比較特殊,如預計12點執行時恰巧shutdown, 重開機已1點, 錯過這個時間沒執行Job就會呼叫這個method
public void triggerComplete(Trigger trigger, JobExecutionContext context, int triggerInstructionCode); // 執行完成。

  和JobListener,也有addGlobalTriggerListener用法。而SchedulerListener的介面,看原始定義大概就能望文生義了。

public interface SchedulerListener {
    public void jobScheduled(Trigger trigger);
    public void jobUnscheduled(String triggerName, String triggerGroup);
    public void triggerFinalized(Trigger trigger);
    public void triggersPaused(String triggerName, String triggerGroup);
    public void triggersResumed(String triggerName,String triggerGroup);
    public void jobsPaused(String jobName, String jobGroup);
    public void jobsResumed(String jobName, String jobGroup);
    public void schedulerError(String msg, SchedulerException cause);
    public void schedulerShutdown();
}

arrow
arrow
    全站熱搜

    Jemmy 發表在 痞客邦 留言(0) 人氣()