【Quartz】持久化到數據庫【五】


  前言

    我們做到這里已經對Quartz定時器組件已經是學會了基本的使用了。但是我們有沒有想過任務開啟之后萬一斷掉了,當機了我們怎么辦,你是否還想繼續執行原先的任務。我們普通的創建是把任務放在內存中存儲,如果內存被釋放掉,任務也就消失了,那怎么辦哪,不得不說這個組件還是很厲害的。他已經幫我們想過了解方案---就是放到數據庫。

  Quartz插一嘴:

    quartz在任務中分為兩種:有狀態和無狀態執行。

    有狀態:對於同一個 trigger 來說,有狀態的 job 不能被並行執行,只有上一次觸發的任務被執行完之后,才能觸發下一次執行。所有我自己理解為串行的順序執行(自己怎么好記怎么理解 哈哈)

   無狀態:無狀態任務一般指可以並發的任務,即任務之間是獨立的,不會互相干擾。就是各自干各自的。

數據庫概貌:

    首先上一下sql腳本下載地址:sql數據庫rar文件下載

 表結構瞅一瞅:

下面是表代表的大致意思吧:

 

表名

描述

QRTZ_BLOB_TRIGGERS

作為 Blob 類型存儲(用於 Quartz 用戶用 JDBC 創建他們自己定制的 Trigger 類型,JobStore 並不知道如何存儲實例的時候)

QRTZ_CALENDARS

以 Blob 類型存儲 Quartz 的 Calendar 信息

QRTZ_CRON_TRIGGERS

存儲 Cron Trigger,包括 Cron 表達式和時區信息

QRTZ_FIRED_TRIGGERS

存儲與已觸發的 Trigger 相關的狀態信息,以及相聯 Job 的執行信息

QRTZ_JOB_DETAILS

存儲每一個已配置的 Job 的詳細信息

QRTZ_LOCKS

存儲程序的非觀鎖的信息(假如使用了悲觀鎖)

QRTZ_PAUSED_TRIGGER_GRPS

存儲已暫停的 Trigger 組的信息

QRTZ_SCHEDULER_STATE

存儲少量的有關 Scheduler 的狀態信息,和別的 Scheduler 實例(假如是用於一個集群中)

QRTZ_SIMPLE_TRIGGERS

存儲簡單的 Trigger,包括重復次數,間隔,以及已觸的次數

QRTZ_SIMPROP_TRIGGERS

 

QRTZ_TRIGGERS

存儲已配置的 Trigger 的信息

 代碼部分:

    工具都有了那就干活吧,既然我上面說了任務分為有狀態和無狀態,那正好借這個例子一起給介紹一下。首先還是我們的老朋友任務的創建:

這是一個無狀態任務

 public class ServerJob : IJob
    {
        private const string Count = "count";
        public virtual void Execute(IJobExecutionContext context)
        {
            JobKey jobKey = context.JobDetail.Key;
            try
            {
                // 如果任務是恢復的任務的話
                if (context.Recovering)
                {
                    WritTxt.WriteFile("serversql", jobKey+":恢復打印");
                }
                else
                {
                    WritTxt.WriteFile("serversql", jobKey+":啟動打印");
                }
                JobDataMap data = context.JobDetail.JobDataMap;
                int count;
                if (data.ContainsKey(Count))
                {
                    count = data.GetInt(Count);
                }
                else
                {
                    count = 0;
                }
                count++;
                data.Put(Count, count);

                WritTxt.WriteFile("serversql", string.Format("結束: {0} done at {1}\n 累計數 #{2}", jobKey, DateTime.Now.ToString("r"), count));
            }
            catch (Exception ex)
            {

            }
        }
    }

下面是一個有狀態任務,因為本人比較懶所有就不寫新任務了,直接繼承了無狀態任務事件。

    [PersistJobDataAfterExecution] //代表當前任務是否有狀態
    [DisallowConcurrentExecution]//代表任務不允許並發
    public class ServerJobState : ServerJob
    {
    }

下面就是我們要說的重點了;數據庫配置

只需要在實例化調度器前把我們的數據庫配置傳進去就好了。

/// <summary>
        /// 持久化屬性
        /// </summary>
        NameValueCollection properties = new NameValueCollection();
        public ExampleServer()
        {       
            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.dataSource"] = "default";
            properties["quartz.jobStore.tablePrefix"] = "QRTZ_";
            properties["quartz.jobStore.clustered"] = "true";
            properties["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.SqlServerDelegate, Quartz";

            properties["quartz.dataSource.default.connectionString"] = "Server=(local);Database=quartz;Trusted_Connection=True;";
            properties["quartz.dataSource.default.provider"] = "SqlServer-20";

            // First we must get a reference to a scheduler
            ISchedulerFactory sf = new StdSchedulerFactory(properties);
            Scheduler = sf.GetScheduler();
        }

然后就是運行測試了,這里我用了不同的形式返回了調度器和調度工廠。這樣子也挺好用的,可以把以前的那種方法改成這種。

 /// <summary>
        /// 調度工廠
        /// </summary>
        private static StdSchedulerFactory SchedulerFactory { get; set; }

        /// <summary>
        /// 調度接口
        /// </summary>
        private static IScheduler Scheduler { get; set; }


        #region 0.測試
        public void Run()
        {
            string schedId = Scheduler.SchedulerInstanceId;
            IJobDetail job = JobBuilder.Create<ServerJob>()
                           .WithIdentity("ServerJob", schedId)
                           .RequestRecovery()
                           .Build();


            ITrigger trigger = TriggerBuilder.Create()
                                          .WithIdentity("serverTrigger", schedId)
                                          .WithCronSchedule("0/10 * * * * ?")     //5秒執行一次
                                          .Build();
            //已存在就不重復添加
            try
            {
                Scheduler.ScheduleJob(job, trigger);
            }
            catch (Exception ex)
            {

            }
            IJobDetail jobState = JobBuilder.Create<ServerJobState>()
                           .WithIdentity("ServerJobSatte", schedId)
                           .RequestRecovery()
                           .Build();


            ITrigger triggerState = TriggerBuilder.Create()
                                          .WithIdentity("serverTriggerSatte", schedId)
                                          .WithCronSchedule("0/10 * * * * ?")     //5秒執行一次
                                          .Build();
            //已存在就不重復添加
            try
            {
                Scheduler.ScheduleJob(jobState, triggerState);
            }
            catch (Exception ex)
            {

            }
            //啟動
            Scheduler.Start();

        }
        #endregion

最后就是大結局了,讓我們看下運行結果吧:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM