Quartz.NET提供了集羣的配置,這個集羣並不能達到負載均衡的效果,而僅僅提供了故障轉移的功能,主要場景是:兩個節點的Quartz.NET任務服務器同時連接到另一個節點的數據庫服務器,當一個任務服務器宕機時,另一個任務服務器會啓動。
集羣的主要配置如下:
properties["quartz.jobStore.clustered"] = "true";
總的代碼如下:
[PersistJobDataAfterExecution]
[DisallowConcurrentExecution]
public class SimpleRecoveryJob : IJob
{
private static readonly ILog log = LogManager.GetLogger(typeof (SimpleRecoveryJob));
public const string Count = "count";
public virtual void Execute(IJobExecutionContext context)
{
JobKey jobKey = context.JobDetail.Key;
if (context.Recovering)
{
log.InfoFormat("SimpleRecoveryJob: {0} 恢復時間 at {1}", jobKey, DateTime.Now.ToString());
}
else
{
log.InfoFormat("SimpleRecoveryJob: {0} 開始執行 {1}", jobKey, DateTime.Now.ToString());
}
int delay = 10*1000;
Thread.Sleep(delay);
JobDataMap data = context.JobDetail.JobDataMap;
int count;
if (data.ContainsKey(Count))
{
count = data.GetInt(Count);
}
else
{
count = 0;
}
count++;
data.Put(Count, count);
log.InfoFormat("SimpleRecoveryJob: {0} 完成 {1}\n 執行第 #{2}次", jobKey, DateTime.Now.ToString(), count);
}
}
public class ClusterExample
{
private static ILog log = LogManager.GetLogger(typeof (ClusterExample));
public static void Run(bool inClearJobs, bool inScheduleJobs)
{
NameValueCollection properties = new NameValueCollection();
properties["quartz.scheduler.instanceName"] = "TestScheduler";
properties["quartz.scheduler.instanceId"] = "instance_one";
properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
properties["quartz.threadPool.threadCount"] = "5";
properties["quartz.threadPool.threadPriority"] = "Normal";
properties["quartz.jobStore.misfireThreshold"] = "60000";
properties["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz";
properties["quartz.jobStore.useProperties"] = "false";
properties["quartz.jobStore.clustered"] = "true";
// SQLit必須添加如下配置
// properties["quartz.jobStore.lockHandler.type"] = "Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz";
//存儲類型
properties["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz";
//表明前綴
properties["quartz.jobStore.tablePrefix"] = "QRTZ_";
//驅動類型
properties["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz";
//數據源名稱
properties["quartz.jobStore.dataSource"] = "myDS";
//連接字符串
properties["quartz.dataSource.myDS.connectionString"] = @"Data Source=(local);Initial Catalog=quartz;User ID=sa;Password=123";
//sqlserver版本
properties["quartz.dataSource.myDS.provider"] = "SqlServer-20";
ISchedulerFactory sf = new StdSchedulerFactory(properties);
IScheduler sched = sf.GetScheduler();
if (inClearJobs)
{
log.Info("正在刪除所有記錄");
sched.Clear();
}
if (inScheduleJobs)
{
string schedId = sched.SchedulerInstanceId;
int count = 1;
IJobDetail job = JobBuilder.Create<SimpleRecoveryJob>()
.WithIdentity("job_" + count, schedId)
.RequestRecovery() //故障恢復
.Build();
job.JobDataMap.Put(SimpleRecoveryJob.Count,1);
ISimpleTrigger trigger = (ISimpleTrigger) TriggerBuilder.Create()
.WithIdentity("triger_" + count, schedId)
.StartAt(DateBuilder.FutureDate(1, IntervalUnit.Second))
.WithSimpleSchedule(x =>x.RepeatForever().WithInterval(TimeSpan.FromSeconds(5)))
.Build();
log.InfoFormat("{0} 開始時間 {1} 重複次數 {2}, 重複間隔 {3}", job.Key, trigger.GetNextFireTimeUtc(), trigger.RepeatCount, trigger.RepeatInterval.TotalSeconds);
sched.ScheduleJob(job, trigger);
}
sched.Start();
log.Info("------- 開始計劃 ----------------");
log.Info("------- 等待1小時 ----------");
Thread.Sleep(TimeSpan.FromHours(1));
sched.Shutdown();
log.Info("------- 結束計劃 ----------------");
}
public static void Run()
{
ClusterExample.Run(false, false);
}
}
當一個任務服務器宕機時,另一臺任務服務器啓動會重新從數據庫中找到上次執行失敗前的狀態重新開始執行。