.net 5中配置Quartz集群


准備工作:

Quartz.net官方關於配置集群的文檔:https://www.quartz-scheduler.net/documentation/quartz-2.x/tutorial/job-stores.html#ramjobstore

本篇文章內容參考自:https://www.cnblogs.com/JulianHuang/p/12720436.html

1、數據庫中添加幾張表

根據自己的數據庫類型,自行進入這個地址復制SQL執行:https://github.com/quartznet/quartznet/tree/master/database/tables

以下內容均以 Mysql 為例

2、修改startup中依賴注入的代碼


改為:

services.AddSingleton<ISchedulerFactory>(u => {
    DbProvider.RegisterDbMetadata("mysql-custom", new DbMetadata()
    {
        AssemblyName = typeof(MySqlConnection).Assembly.GetName().Name,
        ConnectionType = typeof(MySqlConnection),
        CommandType = typeof(MySqlCommand),
        ParameterType = typeof(MySqlParameter),
        ParameterDbType = typeof(DbType),
        ParameterDbTypePropertyName = "DbType",
        ParameterNamePrefix = "@",
        ExceptionType = typeof(MySqlException),
        BindByName = true
   });
   var properties = new NameValueCollection
   {
       ["quartz.jobStore.type"] = "Quartz.Impl.AdoJobStore.JobStoreTX, Quartz", // 配置Quartz以使用JobStoreTx
       ["quartz.jobStore.useProperties"] = "true", // 配置AdoJobStore以將字符串用作JobDataMap值
       ["quartz.jobStore.dataSource"] = "myDS", // 配置數據源名稱
       ["quartz.jobStore.tablePrefix"] = "QRTZ_", // quartz所使用的表,在當前數據庫中的表前綴
       ["quartz.jobStore.driverDelegateType"] = "Quartz.Impl.AdoJobStore.StdAdoDelegate, Quartz",  // 配置AdoJobStore使用的DriverDelegate
       ["quartz.dataSource.myDS.connectionString"] = "server=localhost;uid=root;pwd=123;database=quartzsample", // 配置數據庫連接字符串,自己處理好連接字符串,我這里就直接這么寫了
       ["quartz.dataSource.myDS.provider"] = "mysql-custom", // 配置數據庫提供程序(這里是自定義的,定義的代碼在上面)
       ["quartz.jobStore.lockHandler.type"] = "Quartz.Impl.AdoJobStore.UpdateLockRowSemaphore, Quartz",
       ["quartz.serializer.type"] = "binary",
       ["quartz.jobStore.clustered"] = "true",    //  指示Quartz.net的JobStore是應對 集群模式
       ["quartz.scheduler.instanceId"] = "AUTO"
    };
    return new StdSchedulerFactory(properties);
});

注意改一下數據庫連接字符串

3、修改 QuartzHostedService 類


修改 StartAsync 這個方法的內容,在 foreach 循環體內部添加一行 if 判斷語句
原來的代碼為:

需要改成:

 /// <summary>
 /// 批量啟動定時任務
 /// </summary>
 /// <param name="cancellationToken"></param>
 /// <returns></returns>
 public async Task StartAsync(CancellationToken cancellationToken)
 {
     _scheduler = await _schedulerFactory.GetScheduler(cancellationToken);
     _scheduler.JobFactory = _jobFactory;

     // 循環遍歷startup里注冊的作業
     foreach (var jobSchedule in _jobSchedules)
     {
         // 判斷數據庫中有沒有記錄過,有的話,quartz會自動從數據庫中提取信息創建 schedule
         if (!await _scheduler.CheckExists(new JobKey(GenerateIdentity(jobSchedule, IdentityType.Job))) &&
          !await _scheduler.CheckExists(new TriggerKey(GenerateIdentity(jobSchedule, IdentityType.Trigger))))
         {
             var job = CreateJob(jobSchedule);
             var trigger = CreateTrigger(jobSchedule);

             await _scheduler.ScheduleJob(job, trigger, cancellationToken);
         }
     }

     await _scheduler.Start();
}

3、目前集群已配置完成,進入項目根目錄,開三個 cmd 用來在本地模擬集群


復制下面這條語句,粘貼到 cmd,然后每個 cmd 里面都修改成不同的端口號

dotnet run --urls=http://*:10086

首先先只運行兩個程序,然后觀察規律

仔細觀察兩個端口,你可以發現,同樣的代碼,但是定時任務並不會同時被兩個進程去執行,他只會執行一個,那現在我把右邊的給停下來

這個時候你就能發現,右邊那個停止之后,左邊的不僅會執行 job2 ,而且還會執行 job1
那如果是三個又會怎么樣呢

現在我再把兩邊的給關掉,只留中間的那個

Quartz借助數據庫,使用悲觀鎖的方式,達到即使部署了多台機器,同一個定時任務也不會連續被幾台服務機一起執行的結果。當一台機掛了,這時其他機器接過上台機的接力棒繼續跑,從而做到高可用。

本篇文章代碼地址:https://github.com/shapmanLv/QuartzSample


免責聲明!

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



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